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"
41 #include "AliRawDataHeader.h"
45 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDetectorId = 0xA00;
46 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLOffSet = 0;
47 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkNofDDL = 20;
48 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLHeaderSize = 8;
49 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkLutLine = 59648 + 1;
50 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkMaxNofDataPerDetElem = 3000;
51 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkNofDetElemInDDL[20] = { 2, 2, 2, 2,
56 const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkMinDetElemIdInDDL[20] = { 100, 101, 200, 201,
63 AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
68 fkBuspatchHeaderSize(4),
71 fkLookUpTableData(NULL),
73 fRecPointsCount(NULL),
74 fMaxRecPointsCount(0),
78 fGenerateClusterInfo(false),
84 fGenerateChannelInfo(false),
89 fDataCountListPerDetElem(NULL),
90 fNofDataInDetElem(NULL),
91 fCentralChargeB(NULL),
92 fCentralChargeNB(NULL),
101 fNofYNeighbour(NULL),
103 fkMaxEntryPerBusPatch(0),
104 fRecoveryMode(kDontTryRecover)
106 /// Default constructor
108 fkBlockHeaderSize = 8;
110 fkBuspatchHeaderSize = 4;
114 fPadData = new AliHLTMUONPad[fgkLutLine];
116 catch (const std::bad_alloc&)
118 HLTError("Dynamic memory allocation failed for fPadData in constructor.");
122 fPadData[0].fDetElemId = 0;
123 fPadData[0].fIX = 0 ;
124 fPadData[0].fIY = 0 ;
125 fPadData[0].fRealX = 0.0 ;
126 fPadData[0].fRealY = 0.0 ;
127 fPadData[0].fRealZ = 0.0 ;
128 fPadData[0].fHalfPadSize = 0.0 ;
129 fPadData[0].fPlane = -1 ;
130 fPadData[0].fCharge = 0 ;
131 fPadData[0].fBusPatch = -1;
132 fPadData[0].fRawData = 0 ;
134 bzero(fGetIdTotalData, 336*237*2*sizeof(int));
138 AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
140 /// Default destructor
148 if (fClusters != NULL)
152 if (fChannels != NULL)
159 void AliHLTMUONHitReconstructor::SetLookUpTable(
160 const AliHLTMUONHitRecoLutRow* lookupTable,
161 const IdManuChannelToEntry* idToEntry,
162 const MaxEntryPerBusPatch* maxEntryPerBP
165 /// Sets the Lookup table (LUT) containing the position of each pad with
166 /// electronic channel associated with it. Also the appropriate manu
167 /// channel ID mapping to LUT row is also set.
169 assert( lookupTable != NULL );
170 assert( idToEntry != NULL );
171 assert( maxEntryPerBP != NULL );
173 fkLookUpTableData = lookupTable;
174 fkIdToEntry = idToEntry;
175 fkMaxEntryPerBusPatch = maxEntryPerBP;
178 bool AliHLTMUONHitReconstructor::DeInitDetElemInDDLArray()
182 if (fDataCountListPerDetElem)
184 delete [] fDataCountListPerDetElem;
185 fDataCountListPerDetElem = NULL;
188 if (fNofDataInDetElem)
190 delete [] fNofDataInDetElem;
191 fNofDataInDetElem = NULL;
197 bool AliHLTMUONHitReconstructor::InitDetElemInDDLArray()
202 if(GetkNofDetElemInDDL(fDDL)==-1){
203 HLTError("Check if the DDLNumber(AliHLTInt32_t value) is Set before this method");
208 fDataCountListPerDetElem = new AliHLTUInt16_t*[GetkNofDetElemInDDL(fDDL)];
209 }catch (const std::bad_alloc&){
210 HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
214 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
216 fDataCountListPerDetElem[idet] = new AliHLTUInt16_t[fgkMaxNofDataPerDetElem];
217 }catch (const std::bad_alloc&){
218 HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem[%d]",idet);
223 fNofDataInDetElem = new AliHLTUInt16_t[GetkNofDetElemInDDL(fDDL)];
224 }catch (const std::bad_alloc&){
225 HLTError("Dynamic memory allocation failed in constructor : fDataCountListPerDetElem");
229 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
230 fNofDataInDetElem[idet] = 0;
235 void AliHLTMUONHitReconstructor::TryRecover(ERecoveryMode mode)
237 /// Sets if the decoder should enable the error recovery logic.
239 // Here we setup the various flags to control exactly how the DDL raw data
240 // decoder will behave and what output is generated during errors.
241 fRecoveryMode = mode;
245 fHLTMUONDecoder.TryRecover(true);
246 fHLTMUONDecoder.ExitOnError(false);
247 fHLTMUONDecoder.GetHandler().WarnOnly(true);
248 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
250 case kRecoverJustSkip:
251 fHLTMUONDecoder.TryRecover(false);
252 fHLTMUONDecoder.ExitOnError(false);
253 fHLTMUONDecoder.GetHandler().WarnOnly(true);
254 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
256 case kRecoverFromParityErrorsOnly:
257 fHLTMUONDecoder.TryRecover(false);
258 fHLTMUONDecoder.ExitOnError(false);
259 fHLTMUONDecoder.GetHandler().WarnOnly(false);
260 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
263 fRecoveryMode = kDontTryRecover;
264 fHLTMUONDecoder.TryRecover(false);
265 fHLTMUONDecoder.ExitOnError(true);
266 fHLTMUONDecoder.GetHandler().WarnOnly(false);
267 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(false);
273 bool AliHLTMUONHitReconstructor::Run(
274 AliHLTUInt32_t* rawData,
275 AliHLTUInt32_t rawDataSize,
276 AliHLTMUONRecHitStruct* const recHit,
277 AliHLTUInt32_t& nofHit
280 // main function called by HLTReconstructor to perform DHLT Hitreconstruction
283 fMaxRecPointsCount = nofHit;
284 fRecPointsCount = &nofHit;
285 *fRecPointsCount = 0;
289 HLTDebug("Decoding for DDL : %d",fDDL);
290 if(GetkMinDetElemIdInDDL(fDDL) == -1 or GetkNofDetElemInDDL(fDDL)==-1){
291 HLTError("DDL value fDDL : %d, out of range",fDDL);
293 if (not DecodeDDL(rawData, rawDataSize)) {
294 // Dont need to log any message again. Already done so in DecodeDDL.
298 if (fDigitPerDDL == 1)
300 // There are no digits to process so stop here.
304 // Allocate fClusters and fChannels if required to do so and only if the allocated
305 // size of the arrays is too small.
308 if (fGenerateClusterInfo and fMaxClusters < fMaxRecPointsCount)
310 if (fClusters != NULL)
315 fClusters = new AliHLTMUONClusterStruct[fMaxRecPointsCount];
316 fMaxClusters = fMaxRecPointsCount;
318 if (fGenerateChannelInfo and fMaxChannels < fMaxRecPointsCount*fMaxChannelMult)
320 if (fChannels != NULL)
325 fChannels = new AliHLTMUONChannelStruct[fMaxRecPointsCount*fMaxChannelMult];
326 fMaxChannels = fMaxRecPointsCount*fMaxChannelMult;
329 catch(const std::bad_alloc&)
331 HLTError("Could not allocate memory for the extra cluster and channel information.");
335 if (not FindRecHits()) {
336 HLTError("Failed to generate RecHits");
344 bool AliHLTMUONHitReconstructor::FillClusterData(
345 AliHLTMUONClusterStruct* clusters, AliHLTUInt32_t& nofClusters
348 /// Fills the output clusters array with extra cluster information.
350 bool sizeOk = fClusterCount <= nofClusters;
351 AliHLTUInt32_t n = sizeOk ? fClusterCount : nofClusters;
352 memcpy(clusters, fClusters, sizeof(AliHLTMUONClusterStruct)*n);
358 bool AliHLTMUONHitReconstructor::FillChannelData(
359 AliHLTMUONChannelStruct* channels, AliHLTUInt32_t& nofChannels
362 /// Fills the output channels array with extra channel information for each cluster.
364 bool sizeOk = fChannelCount <= nofChannels;
365 AliHLTUInt32_t n = sizeOk ? fChannelCount : nofChannels;
366 memcpy(channels, fChannels, sizeof(AliHLTMUONChannelStruct)*n);
372 bool AliHLTMUONHitReconstructor::DecodeDDL(AliHLTUInt32_t* rawData,AliHLTUInt32_t rawDataSize)
374 //function to decode Raw Data
376 AliHLTMUONRawDecoder& handler = reinterpret_cast<AliHLTMUONRawDecoder&>(fHLTMUONDecoder.GetHandler());
377 UInt_t bufferSize = UInt_t(rawDataSize*sizeof(AliHLTUInt32_t));
379 handler.SetDCCut(fDCCut);
380 handler.SetPadData(fPadData);
381 handler.SetLookUpTable(fkLookUpTableData);
382 handler.SetIdManuChannelToEntry(fkIdToEntry);
383 handler.DDLNumber(fDDL);
384 handler.SetNofFiredDetElemId(fNofDataInDetElem);
385 handler.SetMaxFiredPerDetElem(fDataCountListPerDetElem);
386 handler.SetMaxEntryPerBusPatch(fkMaxEntryPerBusPatch);
388 if (not fHLTMUONDecoder.Decode(rawData,bufferSize))
390 switch (TryRecover())
393 // Do not print the following warning for option "-dontprintparityerrors" if there
394 // were only parity errors.
395 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
396 (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
399 HLTWarning("There was a problem with the raw data."
400 " Recovered as much data as possible."
401 " Will continue processing the next event."
405 case kRecoverJustSkip:
406 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound() or
407 (fHLTMUONDecoder.GetHandler().ParityErrorFound() and not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
410 HLTWarning("There was a problem with the raw data."
411 " Skipped corrupted data structures."
412 " Will continue processing the next event."
416 case kRecoverFromParityErrorsOnly:
417 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound())
419 HLTError("Failed to decode the tracker DDL raw data.");
422 if (not fHLTMUONDecoder.GetHandler().DontPrintParityErrors())
424 assert( fHLTMUONDecoder.GetHandler().ParityErrorFound() );
425 HLTWarning("Found parity errors in the raw data,"
426 " but will continue processing."
431 HLTError("Failed to decode the tracker DDL raw data.");
436 fDigitPerDDL = handler.GetDataCount();
438 // fMaxFiredPerDetElem[fNofFiredDetElem-1] = handler.GetDataCount();
440 // HLTDebug("fNofFiredDetElem : %d, NofDigits %d and max reco point limit is : %d, nofDetElems : %d",
441 // fNofFiredDetElem,fDigitPerDDL,fMaxRecPointsCount,fNofFiredDetElem);
443 // for(int iDet=0; iDet<TMath::Max(fNofFiredDetElem,130); iDet++)
444 // HLTDebug("NofCount (fMaxFiredPerDetElem) in iDet %d is : %d", iDet, fMaxFiredPerDetElem[iDet]);
446 // if(fNofFiredDetElem>129){
447 // HLTError("Number of fired detection elements is %d, which is more than 129.", fNofFiredDetElem);
451 if(fDigitPerDDL == 1){
452 HLTDebug("An Empty DDL file was found.");
459 bool AliHLTMUONHitReconstructor::FindRecHits()
461 // fuction that calls hit reconstruction detector element-wise.
463 assert( fCentralChargeB == NULL );
464 assert( fCentralChargeNB == NULL );
465 assert( fRecX == NULL );
466 assert( fRecY == NULL );
467 assert( fAvgChargeX == NULL );
468 assert( fAvgChargeY == NULL );
469 assert( fTotChargeX == NULL );
470 assert( fTotChargeY == NULL );
471 assert( fNofBChannel == NULL );
472 assert( fNofNBChannel == NULL );
473 assert( fNofYNeighbour == NULL );
475 bool resultOk = false;
479 for(int iDet=0; iDet< GetkNofDetElemInDDL(fDDL) ; iDet++)
486 fCentralChargeB = new int[fNofDataInDetElem[iDet]];
487 HLTDebug("Allocated fCentralChargeB with %d elements.", fNofDataInDetElem[iDet]);
488 fCentralChargeNB = new int[fNofDataInDetElem[iDet]];
489 HLTDebug("Allocated fCentralChargeNB with %d elements.", fNofDataInDetElem[iDet]);
492 catch(const std::bad_alloc&)
494 HLTError("Dynamic memory allocation failed for fCentralChargeNB and fCentralChargeB");
496 //break; Do not break. Might have smaller memory requirements in the next iteration.
499 // Continue processing, but check if everything is OK as we do, otherwise
500 // do not execute the next steps.
503 HLTDebug("Finding central hists for nofDigit : %d, to in iDet : %4d and min detelem : %4d",
504 fNofDataInDetElem[iDet],iDet,GetkMinDetElemIdInDDL(fDDL));
505 FindCentralHits(iDet);
507 HLTDebug("For iDet : %d, Found fCentralCountB : %d, fCentralCountNB : %d",iDet,fCentralCountB,fCentralCountNB);
508 if(fCentralCountB==0 or fCentralCountNB==0)
510 HLTDebug("There is no fired pad in bending/nonbending plane...skipping this detection element");
511 if (fCentralChargeB != NULL)
513 delete [] fCentralChargeB;
514 HLTDebug("Released fCentralChargeB array.");
515 fCentralChargeB = NULL;
517 if (fCentralChargeNB != NULL)
519 delete [] fCentralChargeNB;
520 HLTDebug("Released fCentralChargeNB array.");
521 fCentralChargeNB = NULL;
531 fRecY = new float[fCentralCountB];
532 HLTDebug("Allocated fRecY with %d elements.", fCentralCountB);
533 fRecX = new float[fCentralCountNB];
534 HLTDebug("Allocated fRecX with %d elements.", fCentralCountNB);
535 fAvgChargeY = new float[fCentralCountB];
536 HLTDebug("Allocated fAvgChargeY with %d elements.", fCentralCountB);
537 fAvgChargeX = new float[fCentralCountNB];
538 HLTDebug("Allocated fAvgChargeX with %d elements.", fCentralCountNB);
539 fTotChargeY = new float[fCentralCountB];
540 HLTDebug("Allocated fTotChargeY with %d elements.", fCentralCountB);
541 fTotChargeX = new float[fCentralCountNB];
542 HLTDebug("Allocated fTotChargeX with %d elements.", fCentralCountNB);
543 fNofBChannel = new int[fCentralCountB];
544 HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
545 fNofNBChannel = new int[fCentralCountNB];
546 HLTDebug("Allocated fNofNBChannel with %d elements.", fCentralCountNB);
547 fNofYNeighbour = new int[fCentralCountB];
548 HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
551 catch(const std::bad_alloc&){
552 HLTError("Dynamic memory allocation failed for internal arrays.");
554 //break; Must not break, this will prevent calling delete and memory cleanup, i.e. memory leak.
558 if (resultOk) RecXRecY();
563 resultOk = MergeQuadRecHits();
565 resultOk = MergeSlatRecHits();
568 // minimum value in loop is 1 because dataCount in ReadDDL starts from 1 instead of 0;
569 for(int i=0;i<fNofDataInDetElem[iDet];i++)
570 fGetIdTotalData[fPadData[fDataCountListPerDetElem[iDet][i]].fIX]
571 [fPadData[fDataCountListPerDetElem[iDet][i]].fIY]
572 [fPadData[fDataCountListPerDetElem[iDet][i]].fPlane] = 0;
574 // Make sure to release any memory that was allocated.
575 if (fCentralChargeB != NULL)
577 delete [] fCentralChargeB;
578 HLTDebug("Released fCentralChargeB array.");
579 fCentralChargeB = NULL;
581 if (fCentralChargeNB != NULL)
583 delete [] fCentralChargeNB;
584 HLTDebug("Released fCentralChargeNB array.");
585 fCentralChargeNB = NULL;
590 HLTDebug("Released fRecX array.");
596 HLTDebug("Released fRecY array.");
599 if (fAvgChargeX != NULL)
601 delete [] fAvgChargeX;
602 HLTDebug("Released fAvgChargeX array.");
605 if (fAvgChargeY != NULL)
607 delete [] fAvgChargeY;
608 HLTDebug("Released fAvgChargeY array.");
611 if (fTotChargeX != NULL)
613 delete [] fTotChargeX;
614 HLTDebug("Released fTotChargeX array.");
617 if (fTotChargeY != NULL)
619 delete [] fTotChargeY;
620 HLTDebug("Released fTotChargeY array.");
623 if (fNofBChannel != NULL)
625 delete [] fNofBChannel;
626 HLTDebug("Released fNofBChannel array.");
629 if (fNofNBChannel != NULL)
631 delete [] fNofNBChannel;
632 HLTDebug("Released fNofNBChannel array.");
633 fNofNBChannel = NULL;
635 if (fNofYNeighbour != NULL)
637 delete [] fNofYNeighbour;
638 HLTDebug("Released fNofYNeighbour array.");
639 fNofYNeighbour = NULL;
643 Clear(); // clear internal arrays.
649 void AliHLTMUONHitReconstructor::FindCentralHits(int iDet)
651 // to find central hit associated with each cluster
653 assert( fCentralChargeB != NULL );
654 assert( fCentralChargeNB != NULL );
657 int idManuChannelCentral;
661 for(int iEntry=0;iEntry<fNofDataInDetElem[iDet];iEntry++){
663 iPad = fDataCountListPerDetElem[iDet][iEntry];
665 //if(fPadData[iPad].fDetElemId==102)
666 HLTDebug("iPad : %d, detElem : %d, fCentralCountB : %d, fCentralCountNB : %d",iPad,fPadData[iPad].fDetElemId,fCentralCountB,fCentralCountNB);
668 fGetIdTotalData[fPadData[iPad].fIX]
670 [fPadData[iPad].fPlane] = iPad ;
672 if(fPadData[iPad].fCharge <= fDCCut ) continue;
674 if(fPadData[iPad].fPlane == 0 ){//&& fPadData[iPad].fIY > (0+1) && fPadData[iPad].fIY < (79 - 1)){
675 //if(fPadData[iPad].fIY > 0){
676 if(fCentralCountB>0){
678 for(b = 0;b<fCentralCountB;b++){
679 idManuChannelCentral = fCentralChargeB[b];
680 if(fPadData[iPad].fIX == fPadData[idManuChannelCentral].fIX
683 == fPadData[idManuChannelCentral].fIY + 1
686 == fPadData[idManuChannelCentral].fIY + 2
689 == fPadData[idManuChannelCentral].fIY - 2
692 == fPadData[idManuChannelCentral].fIY - 1)){
695 if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
696 fCentralChargeB[b] = iPad;
697 }// if condn on pad charge
698 }// if condon on pad position
701 fCentralChargeB[fCentralCountB] = iPad;
706 fCentralChargeB[fCentralCountB] = iPad;
708 }// check the size of centralHitB
709 for(b = 0;b<fCentralCountB;b++){
710 idManuChannelCentral = fCentralChargeB[b];
712 //}// if cond on iY > 2 (to avoid edge value pb)
715 if(fCentralCountNB>0){
717 for(nb = 0;nb<fCentralCountNB;nb++){
718 idManuChannelCentral = fCentralChargeNB[nb];
719 if(fPadData[iPad].fIY == fPadData[idManuChannelCentral].fIY
722 == fPadData[idManuChannelCentral].fIX + 1
725 == fPadData[idManuChannelCentral].fIX + 2
728 == fPadData[idManuChannelCentral].fIX - 2
731 == fPadData[idManuChannelCentral].fIX - 1)){
734 if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
735 fCentralChargeNB[nb] = iPad;
736 }// if condn over to find higher charge
737 }// if condn over to find position
738 }// for loop over presently all nb values
740 fCentralChargeNB[fCentralCountNB] = iPad;
743 }// centralHitNB size test
745 fCentralChargeNB[fCentralCountNB] = iPad;
747 }// centralHitNB size test
749 }// fill for bending and nonbending hit
754 void AliHLTMUONHitReconstructor::RecXRecY()
756 // find reconstructed X and Y for each plane separately
758 assert( fRecX != NULL );
759 assert( fRecY != NULL );
760 assert( fAvgChargeX != NULL );
761 assert( fAvgChargeY != NULL );
762 assert( fTotChargeX != NULL );
763 assert( fTotChargeY != NULL );
764 assert( fNofBChannel != NULL );
765 assert( fNofNBChannel != NULL );
766 assert( fNofYNeighbour != NULL );
775 for(b=0;b<fCentralCountB;b++){
776 idCentral = fCentralChargeB[b];
778 if(fPadData[idCentral].fIY==0)
781 idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
783 if(fPadData[idCentral].fIY==236)
786 idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
789 fTotChargeY[b] = (fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
790 if(fTotChargeY[b]==0.0) continue;
791 fAvgChargeY[b] = fTotChargeY[b]/3.0 ;
793 fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
795 fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
797 fPadData[idLower].fRealY*fPadData[idLower].fCharge
798 )/fTotChargeY[b];//(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
801 fNofYNeighbour[b] = 0;
802 if(fPadData[idLower].fCharge>0.0){
806 if(fPadData[idCentral].fCharge>0.0)
808 if(fPadData[idUpper].fCharge>0.0){
813 HLTDebug("detelem : %d, Y charge : lower : %f, middle : %f, upper : %f",fPadData[idCentral].fDetElemId,fPadData[idLower].fCharge,
814 fPadData[idCentral].fCharge,fPadData[idUpper].fCharge);
816 //collect left coloumn
817 if((fPadData[idCentral].fIX-1)>=0){
819 idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][0];
821 if(fPadData[idLeft].fIY==0)
824 idLower = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
826 if(fPadData[idLeft].fIY==236)
829 idUpper = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
831 fTotChargeY[b] += (fPadData[idLeft].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
833 if(fPadData[idLower].fCharge>0.0)
835 if(fPadData[idLeft].fCharge>0.0)
837 if(fPadData[idUpper].fCharge>0.0)
841 ////////////////////////////////////////////////////
843 //collect right coloumn
844 if((fPadData[idCentral].fIX+1)<=335){
846 idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][0];
848 if(fPadData[idRight].fIY==0)
851 idLower = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
853 if(fPadData[idRight].fIY==236)
856 idUpper = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
858 fTotChargeY[b] += (fPadData[idRight].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge);
860 if(fPadData[idLower].fCharge>0.0)
862 if(fPadData[idRight].fCharge>0.0)
864 if(fPadData[idUpper].fCharge>0.0)
868 //////////////////////////////////////////////////////////////////////////////////
869 HLTDebug("RecY[%d] : %f, nofChannel : %d, detelem : %d",b,fRecY[b],fNofBChannel[b],fPadData[idCentral].fDetElemId);
873 for(nb=0;nb<fCentralCountNB;nb++){
874 idCentral = fCentralChargeNB[nb];
876 if(fPadData[idCentral].fIX==0)
879 idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
881 if(fPadData[idCentral].fIX==335)
884 idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
886 fTotChargeX[nb] = (fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
887 if(fTotChargeX[nb]==0.0) continue;
888 fAvgChargeX[nb] = fTotChargeX[nb]/3.0 ;
890 fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
892 fPadData[idRight].fRealX*fPadData[idRight].fCharge
894 fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
895 )/fTotChargeX[nb];//(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
898 fNofNBChannel[nb] = 0;
899 if(fPadData[idLeft].fCharge>0.0)
900 fNofNBChannel[nb]++ ;
901 if(fPadData[idCentral].fCharge>0.0)
902 fNofNBChannel[nb]++ ;
903 if(fPadData[idRight].fCharge>0.0)
904 fNofNBChannel[nb]++ ;
906 HLTDebug("detelem : %d, X charge left : %f, middle : %f, right : %f",fPadData[idCentral].fDetElemId,fPadData[idLeft].fCharge,
907 fPadData[idCentral].fCharge,fPadData[idRight].fCharge);
911 if((fPadData[idCentral].fIY-1)>=0){
913 idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][1];
915 if(fPadData[idLower].fIX==0)
918 idLeft = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
920 if(fPadData[idLower].fIX==335)
923 idRight = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
925 fTotChargeX[nb] += (fPadData[idLower].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
927 if(fPadData[idLeft].fCharge>0.0)
928 fNofNBChannel[nb]++ ;
929 if(fPadData[idLower].fCharge>0.0)
930 fNofNBChannel[nb]++ ;
931 if(fPadData[idRight].fCharge>0.0)
932 fNofNBChannel[nb]++ ;
935 ////////////////////////////////////////////////////////////
938 if((fPadData[idCentral].fIY+1)<=236){
940 idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][1];
942 if(fPadData[idUpper].fIX==0)
945 idLeft = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
947 if(fPadData[idUpper].fIX==335)
950 idRight = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
952 fTotChargeX[nb] += (fPadData[idUpper].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
954 if(fPadData[idLeft].fCharge>0.0)
955 fNofNBChannel[nb]++ ;
956 if(fPadData[idRight].fCharge>0.0)
957 fNofNBChannel[nb]++ ;
958 if(fPadData[idRight].fCharge>0.0)
959 fNofNBChannel[nb]++ ;
962 ////////////////////////////////////////////////////////////
964 HLTDebug("RecX[%d] : %f, nofChannel : %d",nb,fRecX[nb],fNofNBChannel[nb]);
972 bool AliHLTMUONHitReconstructor::MergeQuadRecHits()
974 // Merge reconstructed hits first over same plane then bending plane with non-bending plane
976 assert( fRecX != NULL );
977 assert( fRecY != NULL );
978 assert( fAvgChargeX != NULL );
979 assert( fAvgChargeY != NULL );
980 assert( fTotChargeX != NULL );
981 assert( fTotChargeY != NULL );
982 assert( fNofBChannel != NULL );
983 assert( fNofNBChannel != NULL );
984 assert( fNofYNeighbour != NULL );
986 int idCentralB=0,idCentralNB=0 ;
991 float halfPadLengthX,halfPadLengthY;
992 bool *isMergedY = new bool[fCentralCountB];
993 bool *isMergedX = new bool[fCentralCountNB];
994 float outsideSpacePoint = 1000000.0 ; /// A space point outside the detector
996 // MERGE Bending Plane hits, which are placed side by side
997 for(int i=0;i<fCentralCountB-1;i++){
998 isMergedY[i] = false;
999 if(fRecY[i] != outsideSpacePoint){
1000 for(int j=i+1;j<fCentralCountB;j++){
1002 if(fCentralChargeB[i]==fCentralChargeB[j]){
1003 fRecY[j] = outsideSpacePoint;
1008 fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
1012 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
1014 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
1017 fRecY[j] != outsideSpacePoint
1019 fRecY[i] != outsideSpacePoint
1022 if(fAvgChargeY[i] > fAvgChargeY[j]){
1023 fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1024 )/(fAvgChargeY[i] + fAvgChargeY[j]);
1025 fRecY[j] = outsideSpacePoint;
1028 fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1029 )/(fAvgChargeY[i] + fAvgChargeY[j]);
1030 fRecY[i] = outsideSpacePoint;
1032 }// search for higher charge
1035 }//if fRecY[i] != outsideSpacePoint
1037 isMergedY[fCentralCountB-1] = false;
1039 // MERGE Non Bending Plane hits, which are placed side by side
1040 for(int i=0;i<fCentralCountNB-1;i++){
1041 isMergedX[i] = false;
1042 if(fRecX[i] != outsideSpacePoint){
1043 for(int j=i+1;j<fCentralCountNB;j++){
1045 if(fCentralChargeNB[i]==fCentralChargeNB[j]){
1046 fRecX[j] = outsideSpacePoint;
1051 fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
1055 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
1057 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
1060 fRecX[j] != outsideSpacePoint
1062 fRecX[i] != outsideSpacePoint
1065 if(fAvgChargeX[i] > fAvgChargeX[j]){
1066 fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1067 )/(fAvgChargeX[i] + fAvgChargeX[j]);
1068 fRecX[j] = outsideSpacePoint;
1071 fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1072 )/(fAvgChargeX[i] + fAvgChargeX[j]);
1073 fRecX[i] = outsideSpacePoint;
1074 }// search for higher charge
1077 }//if fRecX[i] != outsideSpacePoint
1079 isMergedX[fCentralCountNB-1] = false;
1081 // Merge bending Plane hits with Non Bending
1082 for(int b=0;b<fCentralCountB;b++){
1083 if(fRecY[b]!=outsideSpacePoint){
1084 idCentralB = fCentralChargeB[b];
1085 padCenterXB = fPadData[idCentralB].fRealX;
1087 halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
1089 for(int nb=0;nb<fCentralCountNB;nb++){
1090 if(fRecX[nb]!=outsideSpacePoint){
1091 idCentralNB = fCentralChargeNB[nb];
1093 padCenterYNB = fPadData[idCentralNB].fRealY;
1095 halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
1097 if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
1098 diffX = fabsf(fRecX[nb]) - fabsf(padCenterXB);
1100 diffX = fabsf(padCenterXB) - fabsf(fRecX[nb]);
1102 if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
1103 diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
1105 diffY = fabsf(fRecY[b]) - fabsf(padCenterYNB);
1107 if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
1109 isMergedY[b] = true;
1110 isMergedX[nb] = true;
1112 if(fNofYNeighbour[b]==2){
1113 if(fPadData[idCentralB].fDetElemId<104)
1114 fRecY[b] += 0.02*sin(14.5*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1115 else if(fPadData[idCentralB].fDetElemId>=200 && fPadData[idCentralB].fDetElemId<204)
1116 fRecY[b] += 0.02*sin(14.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1118 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1121 if(fPadData[idCentralNB].fDetElemId<204)
1122 fRecX[nb] += 0.095*sin(10.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1123 else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
1124 fRecX[nb] += 0.085*sin(9.0*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1127 // First check that we have not overflowed the buffer.
1128 if((*fRecPointsCount) == fMaxRecPointsCount){
1129 HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
1130 " Output buffer is too small.",
1131 (*fRecPointsCount),fMaxRecPointsCount
1133 delete [] isMergedY;
1134 delete [] isMergedX;
1138 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1139 (fPadData[idCentralB].fDetElemId / 100) - 1,
1140 fPadData[idCentralB].fDetElemId
1142 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1143 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1144 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1145 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1147 if (fGenerateClusterInfo)
1149 if (fClusterCount >= fMaxClusters)
1151 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1152 delete [] isMergedY;
1153 delete [] isMergedX;
1157 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
1159 // Increment the cluster ID and warp it around at 0x03FFFFFF since
1160 // the bottom 5 bits are filled with the source DDL number and the
1161 // sign bit in fClusters[fClusterCount].fId must be positive.
1162 fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1164 fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1165 fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
1166 fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
1167 fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
1168 fClusters[fClusterCount].fChargeB = fTotChargeY[b];
1169 fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
1173 if (fGenerateChannelInfo)
1175 // 3 by 3 pad structure around the central pad for the 2 planes.
1176 int pad[2][3][3] = {{
1182 {0, idCentralNB, 0},
1186 // Find the pad index numbers for the central pads and the pads surrounding them.
1187 // All these pads would have contributed to the cluster as long as their charge is != 0.
1188 if (fPadData[idCentralB].fIY > 0)
1189 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
1190 if (fPadData[idCentralB].fIY < 236)
1191 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
1192 if (fPadData[idCentralB].fIX > 0)
1194 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
1195 pad[0][1][0] = idLeft;
1196 if (fPadData[idLeft].fIY > 0)
1197 pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
1198 if (fPadData[idLeft].fIY < 236)
1199 pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
1201 if (fPadData[idCentralB].fIX < 335)
1203 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
1204 pad[0][1][2] = idRight;
1205 if (fPadData[idRight].fIY > 0)
1206 pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
1207 if (fPadData[idRight].fIY < 236)
1208 pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
1211 if (fPadData[idCentralNB].fIX > 0)
1212 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
1213 if (fPadData[idCentralNB].fIX < 335)
1214 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
1215 if (fPadData[idCentralNB].fIY > 0)
1217 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
1218 pad[1][0][1] = idLower;
1219 if (fPadData[idLower].fIX > 0)
1220 pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
1221 if (fPadData[idLower].fIX < 335)
1222 pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
1224 if (fPadData[idCentralNB].fIY < 236)
1226 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
1227 pad[1][2][1] = idUpper;
1228 if (fPadData[idUpper].fIX > 0)
1229 pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
1230 if (fPadData[idUpper].fIX < 335)
1231 pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
1234 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1236 // Now generate the pad structures from all the pad indices found above.
1237 for (int i = 0; i < 2; i++)
1238 for (int j = 0; j < 3; j++)
1239 for (int k = 0; k < 3; k++)
1241 AliHLTMUONPad& p = fPadData[pad[i][j][k]];
1242 // Skip pads that have zero charge because they would not have
1243 // contributed to the cluster.
1244 if (p.fCharge <= 0) continue;
1246 UShort_t manuId; UChar_t channelId; UShort_t adc;
1247 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1249 fChannels[fChannelCount].fClusterId = clusterId;
1250 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1251 fChannels[fChannelCount].fManu = manuId;
1252 fChannels[fChannelCount].fChannelAddress = channelId;
1253 fChannels[fChannelCount].fSignal = adc;
1254 fChannels[fChannelCount].fRawDataWord = p.fRawData;
1259 HLTDebug("Part 1 : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
1260 fRecPoints[(*fRecPointsCount)].fX,
1261 fRecPoints[(*fRecPointsCount)].fY,
1262 fRecPoints[(*fRecPointsCount)].fZ
1264 (*fRecPointsCount)++;
1265 }//if lies wihtin 5.0 mm
1266 }// condn over fRecX ! = 0.0
1267 }// loop over NB side
1268 }// condn on fRecY[b] != 0.0
1269 }// loop over B side;
1271 //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
1272 for(int b=0;b<fCentralCountB;b++){
1273 if(fRecY[b]!=outsideSpacePoint and !isMergedY[b] and fNofBChannel[b]>2){
1274 idCentralB = fCentralChargeB[b];
1276 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 ;
1278 if(TMath::Abs(400.0*fPadData[idCentralB].fHalfPadSize*fPadData[idCentralB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
1280 if(fNofYNeighbour[b]==2){
1281 if(fPadData[idCentralB].fDetElemId<104)
1282 fRecY[b] += 0.02*sin(14.5*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1283 else if(fPadData[idCentralB].fDetElemId>=200 && fPadData[idCentralB].fDetElemId<204)
1284 fRecY[b] += 0.02*sin(14.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1286 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1289 padCenterXB = fPadData[idCentralB].fRealX;
1290 // if(fPadData[idCentralB].fDetElemId<204)
1291 // padCenterXB += 0.095*sin(10.5*(padCenterXB - fPadData[idCentralB].fRealX)) ;
1292 // else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
1293 // padCenterXB += 0.085*sin(9.0*(padCenterXB - fPadData[idCentralB].fRealX)) ;
1295 // First check that we have not overflowed the buffer.
1296 if((*fRecPointsCount) == fMaxRecPointsCount){
1297 HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
1298 " Output buffer is too small.",
1299 (*fRecPointsCount),fMaxRecPointsCount
1301 delete [] isMergedY;
1302 delete [] isMergedX;
1306 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1307 (fPadData[idCentralB].fDetElemId / 100) - 1,
1308 fPadData[idCentralB].fDetElemId
1310 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1311 fRecPoints[(*fRecPointsCount)].fX = padCenterXB;
1312 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1313 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1315 if (fGenerateClusterInfo)
1317 if (fClusterCount >= fMaxClusters)
1319 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1320 delete [] isMergedY;
1321 delete [] isMergedX;
1325 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
1327 // Increment the cluster ID and warp it around at 0x03FFFFFF since
1328 // the bottom 5 bits are filled with the source DDL number and the
1329 // sign bit in fClusters[fClusterCount].fId must be positive.
1330 fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1332 fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1333 fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
1334 fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
1335 fClusters[fClusterCount].fNchannelsNB = fNofBChannel[b];
1336 fClusters[fClusterCount].fChargeB = fTotChargeY[b];
1337 fClusters[fClusterCount].fChargeNB = fTotChargeY[b];
1341 if (fGenerateChannelInfo)
1343 // 3 by 3 pad structure around the central pad for the 2 planes.
1344 int pad[2][3][3] = {{
1354 // Find the pad index numbers for the central pads and the pads surrounding them.
1355 // All these pads would have contributed to the cluster as long as their charge is != 0.
1356 if (fPadData[idCentralB].fIY > 0)
1357 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
1358 if (fPadData[idCentralB].fIY < 236)
1359 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
1360 if (fPadData[idCentralB].fIX > 0)
1362 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
1363 pad[0][1][0] = idLeft;
1364 if (fPadData[idLeft].fIY > 0)
1365 pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
1366 if (fPadData[idLeft].fIY < 236)
1367 pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
1369 if (fPadData[idCentralB].fIX < 335)
1371 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
1372 pad[0][1][2] = idRight;
1373 if (fPadData[idRight].fIY > 0)
1374 pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
1375 if (fPadData[idRight].fIY < 236)
1376 pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
1379 // For hits only in bending plane no need to copy the information to the non-bending side
1380 // for(int i=0;i<3;i++)
1381 // for(int j=0;j<3;j++)
1382 // pad[1][i][j] = pad[0][i][j];
1385 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1387 // Now generate the pad structures from all the pad indices found above.
1388 for (int i = 0; i < 1; i++)
1389 for (int j = 0; j < 3; j++)
1390 for (int k = 0; k < 3; k++)
1392 AliHLTMUONPad& p = fPadData[pad[i][j][k]];
1393 // Skip pads that have zero charge because they would not have
1394 // contributed to the cluster.
1395 if (p.fCharge <= 0) continue;
1397 UShort_t manuId; UChar_t channelId; UShort_t adc;
1398 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1400 fChannels[fChannelCount].fClusterId = clusterId;
1401 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1402 fChannels[fChannelCount].fManu = manuId;
1403 fChannels[fChannelCount].fChannelAddress = channelId;
1404 fChannels[fChannelCount].fSignal = adc;
1405 fChannels[fChannelCount].fRawDataWord = p.fRawData;
1410 HLTDebug("Part 2 : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
1411 fRecPoints[(*fRecPointsCount)].fX,
1412 fRecPoints[(*fRecPointsCount)].fY,
1413 fRecPoints[(*fRecPointsCount)].fZ
1415 (*fRecPointsCount)++;
1417 }// condn on fRecY[b] != 0.0
1418 }// loop over B side;
1421 //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
1422 for(int nb=0;nb<fCentralCountNB;nb++){
1424 idCentralNB = fCentralChargeNB[nb];
1425 if(fRecX[nb]!=outsideSpacePoint and !isMergedX[nb] and fNofNBChannel[nb]>2){
1427 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 ;
1429 if(TMath::Abs(400.0*fPadData[idCentralNB].fHalfPadSize*fPadData[idCentralNB].fPadSizeXY - minPadArea)> 1.0e-5) continue;
1431 padCenterYNB = fPadData[idCentralNB].fRealY;
1434 // if(fPadData[idCentralNB].fDetElemId<104)
1435 // padCenterYNB += 0.02*sin(14.5*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
1436 // else if(fPadData[idCentralNB].fDetElemId>=200 && fPadData[idCentralNB].fDetElemId<204)
1437 // padCenterYNB += 0.02*sin(14.0*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
1439 // padCenterYNB += 0.025*sin(12.0*(padCenterYNB - fPadData[idCentralNB].fRealY)) ;
1442 if(fPadData[idCentralNB].fDetElemId<204)
1443 fRecX[nb] += 0.095*sin(10.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1444 else //if(fPadData[idCentralNB].fDetElemId>=300 && fPadData[idCentralNB].fDetElemId<404)
1445 fRecX[nb] += 0.085*sin(9.0*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1448 // First check that we have not overflowed the buffer.
1449 if((*fRecPointsCount) == fMaxRecPointsCount){
1450 HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
1451 " Output buffer is too small.",
1452 (*fRecPointsCount),fMaxRecPointsCount
1454 delete [] isMergedY;
1455 delete [] isMergedX;
1459 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1460 (fPadData[idCentralNB].fDetElemId / 100) - 1,
1461 fPadData[idCentralNB].fDetElemId
1463 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1464 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1465 fRecPoints[(*fRecPointsCount)].fY = padCenterYNB;
1466 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralNB].fRealZ;
1468 if (fGenerateClusterInfo)
1470 if (fClusterCount >= fMaxClusters)
1472 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1473 delete [] isMergedY;
1474 delete [] isMergedX;
1478 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
1480 // Increment the cluster ID and warp it around at 0x03FFFFFF since
1481 // the bottom 5 bits are filled with the source DDL number and the
1482 // sign bit in fClusters[fClusterCount].fId must be positive.
1483 fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1485 fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1486 fClusters[fClusterCount].fDetElemId = fPadData[idCentralNB].fDetElemId;
1487 fClusters[fClusterCount].fNchannelsB = fNofNBChannel[nb];
1488 fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
1489 fClusters[fClusterCount].fChargeB = fTotChargeX[nb];
1490 fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
1494 if (fGenerateChannelInfo)
1496 // 3 by 3 pad structure around the central pad for the 2 planes.
1497 int pad[2][3][3] = {{
1503 {0, idCentralNB, 0},
1507 // Find the pad index numbers for the central pads and the pads surrounding them.
1508 // All these pads would have contributed to the cluster as long as their charge is != 0.
1510 if (fPadData[idCentralNB].fIX > 0)
1511 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
1512 if (fPadData[idCentralNB].fIX < 335)
1513 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
1514 if (fPadData[idCentralNB].fIY > 0)
1516 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
1517 pad[1][0][1] = idLower;
1518 if (fPadData[idLower].fIX > 0)
1519 pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
1520 if (fPadData[idLower].fIX < 335)
1521 pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
1523 if (fPadData[idCentralNB].fIY < 236)
1525 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
1526 pad[1][2][1] = idUpper;
1527 if (fPadData[idUpper].fIX > 0)
1528 pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
1529 if (fPadData[idUpper].fIX < 335)
1530 pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
1533 // For hits only in non-bending plane no need to copy the information to the bending side
1534 // for(int i=0;i<3;i++)
1535 // for(int j=0;j<3;j++)
1536 // pad[0][i][j] = pad[1][i][j];
1539 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1541 // Now generate the pad structures from all the pad indices found above.
1542 for (int i = 1; i < 2; i++)
1543 for (int j = 0; j < 3; j++)
1544 for (int k = 0; k < 3; k++)
1546 AliHLTMUONPad& p = fPadData[pad[i][j][k]];
1547 // Skip pads that have zero charge because they would not have
1548 // contributed to the cluster.
1549 if (p.fCharge <= 0) continue;
1551 UShort_t manuId; UChar_t channelId; UShort_t adc;
1552 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1554 fChannels[fChannelCount].fClusterId = clusterId;
1555 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1556 fChannels[fChannelCount].fManu = manuId;
1557 fChannels[fChannelCount].fChannelAddress = channelId;
1558 fChannels[fChannelCount].fSignal = adc;
1559 fChannels[fChannelCount].fRawDataWord = p.fRawData;
1564 HLTDebug("Part 3 : Reconstructed hit (X,Y,Z) : (%f,%f,%f), detelemId : %d",
1565 fRecPoints[(*fRecPointsCount)].fX,
1566 fRecPoints[(*fRecPointsCount)].fY,
1567 fRecPoints[(*fRecPointsCount)].fZ,
1568 fPadData[idCentralNB].fDetElemId
1570 (*fRecPointsCount)++;
1571 }//if lies wihtin 5.0 mm
1572 }// condn over fRecX ! = 0.0
1574 delete [] isMergedY;
1575 delete [] isMergedX;
1580 bool AliHLTMUONHitReconstructor::MergeSlatRecHits()
1582 // Merge reconstructed hits first over same plane then bending plane with non-bending plane
1584 assert( fRecX != NULL );
1585 assert( fRecY != NULL );
1586 assert( fAvgChargeX != NULL );
1587 assert( fAvgChargeY != NULL );
1588 assert( fTotChargeX != NULL );
1589 assert( fTotChargeY != NULL );
1590 assert( fNofBChannel != NULL );
1591 assert( fNofNBChannel != NULL );
1592 assert( fNofYNeighbour != NULL );
1594 int idCentralB,idCentralNB ;
1598 float halfPadLengthX,halfPadLengthY;
1599 bool *isMergedY = new bool[fCentralCountB];
1600 bool *isMergedX = new bool[fCentralCountNB];
1601 float outsideSpacePoint = 1000000.0 ; /// A space point outside the detector
1603 // MERGE Bending Plane hits, which are placed side by side
1604 for(int i=0;i<fCentralCountB-1;i++){
1605 isMergedY[i] = false;
1606 if(fRecY[i] != outsideSpacePoint){
1607 for(int j=i+1;j<fCentralCountB;j++){
1609 if(fCentralChargeB[i]==fCentralChargeB[j]){
1610 fRecY[j] = outsideSpacePoint;
1615 fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
1619 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
1621 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
1624 fRecY[j] != outsideSpacePoint
1626 fRecY[i] != outsideSpacePoint
1629 if(fAvgChargeY[i] > fAvgChargeY[j]){
1630 fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1631 )/(fAvgChargeY[i] + fAvgChargeY[j]);
1632 fRecY[j] = outsideSpacePoint;
1635 fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
1636 )/(fAvgChargeY[i] + fAvgChargeY[j]);
1637 fRecY[i] = outsideSpacePoint;
1639 }// search for higher charge
1642 }//if fRecY[i] != outsideSpacePoint
1644 isMergedY[fCentralCountB-1] = false;
1646 // MERGE Non Bending Plane hits, which are placed side by side
1647 for(int i=0;i<fCentralCountNB-1;i++){
1648 isMergedX[i] = false;
1649 if(fRecX[i] != 0.0){
1650 for(int j=i+1;j<fCentralCountNB;j++){
1652 if(fCentralChargeNB[i]==fCentralChargeNB[j]){
1653 fRecX[j] = outsideSpacePoint;
1658 fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
1662 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
1664 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
1667 fRecX[j] != outsideSpacePoint
1669 fRecX[i] != outsideSpacePoint
1672 if(fAvgChargeX[i] > fAvgChargeX[j]){
1673 fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1674 )/(fAvgChargeX[i] + fAvgChargeX[j]);
1675 fRecX[j] = outsideSpacePoint;
1678 fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
1679 )/(fAvgChargeX[i] + fAvgChargeX[j]);
1680 fRecX[i] = outsideSpacePoint;
1681 }// search for higher charge
1684 }//if fRecX[i] != outsideSpacePoint
1686 isMergedX[fCentralCountNB-1] = false;
1688 // Merge bending Plane hits with Non Bending
1689 for(int b=0;b<fCentralCountB;b++){
1690 if(fRecY[b]!=outsideSpacePoint){
1691 idCentralB = fCentralChargeB[b];
1692 padCenterXB = fPadData[idCentralB].fRealX;
1694 halfPadLengthX = fPadData[idCentralB].fHalfPadSize ;
1696 for(int nb=0;nb<fCentralCountNB;nb++){
1697 if(fRecX[nb]!=outsideSpacePoint){
1698 idCentralNB = fCentralChargeNB[nb];
1700 padCenterYNB = fPadData[idCentralNB].fRealY;
1702 halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
1704 if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
1705 diffX = fabsf(fRecX[nb]) - fabsf(padCenterXB);
1707 diffX = fabsf(padCenterXB) - fabsf(fRecX[nb]);
1709 if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
1710 diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
1712 diffY = fabsf(fRecY[b]) - fabsf(padCenterYNB);
1714 if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
1716 isMergedY[b] = true;
1717 isMergedX[nb] = true;
1719 if(fNofYNeighbour[b]==2){
1720 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
1723 fRecX[nb] += 0.075*sin(9.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
1726 // First check that we have not overflowed the buffer.
1727 if((*fRecPointsCount) == fMaxRecPointsCount){
1728 HLTWarning("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
1729 " Output buffer is too small.",
1730 (*fRecPointsCount),fMaxRecPointsCount
1732 delete [] isMergedY;
1733 delete [] isMergedX;
1737 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
1738 (fPadData[idCentralB].fDetElemId / 100) - 1,
1739 fPadData[idCentralB].fDetElemId
1741 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
1742 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
1743 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
1744 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
1746 if (fGenerateClusterInfo)
1748 if (fClusterCount >= fMaxClusters)
1750 HLTError("Ran out of space in internal cluster array of size %d.", fMaxClusters);
1751 delete [] isMergedY;
1752 delete [] isMergedX;
1756 fClusters[fClusterCount].fId = (fNewClusterId << 5) | fDDL;
1758 // Increment the cluster ID and warp it around at 0x03FFFFFF since
1759 // the bottom 5 bits are filled with the source DDL number and the
1760 // sign bit in fClusters[fClusterCount].fId must be positive.
1761 fNewClusterId = (fNewClusterId + 1) & 0x03FFFFFF;
1763 fClusters[fClusterCount].fHit = fRecPoints[(*fRecPointsCount)];
1764 fClusters[fClusterCount].fDetElemId = fPadData[idCentralB].fDetElemId;
1765 fClusters[fClusterCount].fNchannelsB = fNofBChannel[b];
1766 fClusters[fClusterCount].fNchannelsNB = fNofNBChannel[nb];
1767 fClusters[fClusterCount].fChargeB = fTotChargeY[b];
1768 fClusters[fClusterCount].fChargeNB = fTotChargeX[nb];
1772 if (fGenerateChannelInfo)
1774 // 3 by 3 pad structure around the central pad for the 2 planes.
1775 int pad[2][3][3] = {{
1781 {0, idCentralNB, 0},
1785 // Find the pad index numbers for the central pads and the pads surrounding them.
1786 // All these pads would have contributed to the cluster as long as their charge is != 0.
1787 if (fPadData[idCentralB].fIY > 0)
1788 pad[0][0][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY-1][0];
1789 if (fPadData[idCentralB].fIY < 236)
1790 pad[0][2][1] = fGetIdTotalData[fPadData[idCentralB].fIX][fPadData[idCentralB].fIY+1][0];
1791 if (fPadData[idCentralB].fIX > 0)
1793 int idLeft = fGetIdTotalData[fPadData[idCentralB].fIX-1][fPadData[idCentralB].fIY][0];
1794 pad[0][1][0] = idLeft;
1795 if (fPadData[idLeft].fIY > 0)
1796 pad[0][0][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY-1][0];
1797 if (fPadData[idLeft].fIY < 236)
1798 pad[0][2][0] = fGetIdTotalData[fPadData[idLeft].fIX][fPadData[idLeft].fIY+1][0];
1800 if (fPadData[idCentralB].fIX < 335)
1802 int idRight = fGetIdTotalData[fPadData[idCentralB].fIX+1][fPadData[idCentralB].fIY][0];
1803 pad[0][1][2] = idRight;
1804 if (fPadData[idRight].fIY > 0)
1805 pad[0][0][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY-1][0];
1806 if (fPadData[idRight].fIY < 236)
1807 pad[0][2][2] = fGetIdTotalData[fPadData[idRight].fIX][fPadData[idRight].fIY+1][0];
1810 if (fPadData[idCentralNB].fIX > 0)
1811 pad[1][1][0] = fGetIdTotalData[fPadData[idCentralNB].fIX-1][fPadData[idCentralNB].fIY][1];
1812 if (fPadData[idCentralNB].fIX < 335)
1813 pad[1][1][2] = fGetIdTotalData[fPadData[idCentralNB].fIX+1][fPadData[idCentralNB].fIY][1];
1814 if (fPadData[idCentralNB].fIY > 0)
1816 int idLower = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY-1][1];
1817 pad[1][0][1] = idLower;
1818 if (fPadData[idLower].fIX > 0)
1819 pad[1][0][0] = fGetIdTotalData[fPadData[idLower].fIX-1][fPadData[idLower].fIY][1];
1820 if (fPadData[idLower].fIX < 335)
1821 pad[1][0][2] = fGetIdTotalData[fPadData[idLower].fIX+1][fPadData[idLower].fIY][1];
1823 if (fPadData[idCentralNB].fIY < 236)
1825 int idUpper = fGetIdTotalData[fPadData[idCentralNB].fIX][fPadData[idCentralNB].fIY+1][1];
1826 pad[1][2][1] = idUpper;
1827 if (fPadData[idUpper].fIX > 0)
1828 pad[1][2][0] = fGetIdTotalData[fPadData[idUpper].fIX-1][fPadData[idUpper].fIY][1];
1829 if (fPadData[idUpper].fIX < 335)
1830 pad[1][2][2] = fGetIdTotalData[fPadData[idUpper].fIX+1][fPadData[idUpper].fIY][1];
1833 AliHLTInt32_t clusterId = fGenerateClusterInfo ? fClusters[fClusterCount-1].fId : -1;
1835 // Now generate the pad structures from all the pad indices found above.
1836 for (int i = 0; i < 2; i++)
1837 for (int j = 0; j < 3; j++)
1838 for (int k = 0; k < 3; k++)
1840 AliHLTMUONPad& p = fPadData[pad[i][j][k]];
1841 // Skip pads that have zero charge because they would not have
1842 // contributed to the cluster.
1843 if (p.fCharge <= 0) continue;
1845 UShort_t manuId; UChar_t channelId; UShort_t adc;
1846 AliHLTMUONRawDecoder::UnpackADC(p.fRawData, manuId, channelId, adc);
1848 fChannels[fChannelCount].fClusterId = clusterId;
1849 fChannels[fChannelCount].fBusPatch = p.fBusPatch;
1850 fChannels[fChannelCount].fManu = manuId;
1851 fChannels[fChannelCount].fChannelAddress = channelId;
1852 fChannels[fChannelCount].fSignal = adc;
1853 fChannels[fChannelCount].fRawDataWord = p.fRawData;
1858 HLTDebug("Part 4(Slat) : Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
1859 fRecPoints[(*fRecPointsCount)].fX,
1860 fRecPoints[(*fRecPointsCount)].fY,
1861 fRecPoints[(*fRecPointsCount)].fZ
1863 (*fRecPointsCount)++;
1864 }//if lies wihtin 5.0 mm
1865 }// condn over fRecX ! = 0.0
1866 }// loop over NB side
1867 }// condn on fRecY[b] != 0.0
1868 }// loop over B side;
1871 delete [] isMergedY;
1872 delete [] isMergedX;
1877 void AliHLTMUONHitReconstructor::Clear()
1879 // function to clear internal arrays.
1881 HLTDebug("Clearing fPadData and fNofDataInDetElem buffers.");
1884 for(int iPad=1;iPad<fDigitPerDDL;iPad++){
1885 fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
1886 fPadData[iPad].fDetElemId = 0;
1887 fPadData[iPad].fIX = 0 ;
1888 fPadData[iPad].fIY = 0 ;
1889 fPadData[iPad].fRealX = 0.0 ;
1890 fPadData[iPad].fRealY = 0.0 ;
1891 fPadData[iPad].fRealZ = 0.0 ;
1892 fPadData[iPad].fHalfPadSize = -1 ;
1893 fPadData[iPad].fPlane = -1 ;
1894 fPadData[iPad].fCharge = 0 ;
1895 fPadData[iPad].fBusPatch = -1;
1896 fPadData[iPad].fRawData = 0;
1899 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
1900 fNofDataInDetElem[idet] = 0;
1902 // for(int i=0;i<130;i++)
1903 // fMaxFiredPerDetElem[i] = 0;
1907 AliHLTInt32_t AliHLTMUONHitReconstructor::GetkNofDetElemInDDL(Int_t iDDL)
1909 /// Returns the number of detection elements for a DDL.
1911 if(iDDL>=0 && iDDL<=19)
1912 return fgkNofDetElemInDDL[iDDL];
1918 AliHLTInt32_t AliHLTMUONHitReconstructor::GetkMinDetElemIdInDDL(Int_t iDDL)
1920 /// Returns the first detection element ID for a DDL.
1922 if(iDDL>=0 && iDDL<=19)
1923 return fgkMinDetElemIdInDDL[iDDL];
1929 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::AliHLTMUONRawDecoder() :
1930 fkBufferStart(NULL),
1934 fkLookUpTableData(NULL),
1936 fkMaxEntryPerBusPatch(),
1942 fIdManuChannel(0x0),
1944 fDataCountListPerDetElem(NULL),
1945 fNofDataInDetElem(NULL),
1947 fSkipParityErrors(false),
1948 fDontPrintParityErrors(false),
1949 fPrintParityErrorAsWarning(false),
1950 fParityErrorFound(false),
1951 fNonParityErrorFound(false),
1958 AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
1964 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
1966 /// Called for every new raw DDL data payload being processed.
1967 /// Just clears internal counters.
1968 /// \param buffer The pointer to the raw data buffer.
1970 assert( buffer != NULL );
1971 fkBufferStart = buffer;
1972 // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
1974 for( Int_t idet=0;idet<GetkNofDetElemInDDL(fDDL);idet++)
1975 fNofDataInDetElem[idet] = 0;
1977 fParityErrorFound = false;
1978 fNonParityErrorFound = false;
1982 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnError(ErrorCode code, const void* location)
1984 /// Called if there was an error detected in the raw DDL data.
1985 /// Logs an error message.
1986 /// \param code The error code describing the problem.
1987 /// \param location A pointer to the location in the raw data buffer
1988 /// where the problem was found.
1990 if (code == kParityError)
1992 fParityErrorFound = true;
1996 fNonParityErrorFound = true;
1998 if (fDontPrintParityErrors and code == kParityError) return;
2000 long bytepos = long(location) - long(fkBufferStart) + sizeof(AliRawDataHeader);
2001 if (fWarnOnly or (fPrintParityErrorAsWarning and code == kParityError))
2003 HLTWarning("There is a problem with decoding the raw data."
2004 " %s (Error code: %d, at byte %d). Trying to recover from corrupt data.",
2005 ErrorCodeToMessage(code), code, bytepos
2010 HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
2011 ErrorCodeToMessage(code), code, bytepos
2016 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* /*data*/)
2018 // operation to perform on new data
2019 fBusPatchId = int(header->fBusPatchId);
2020 MaxEntryPerBusPatch& maxEntryPerBusPatch
2021 = * const_cast<MaxEntryPerBusPatch*>(fkMaxEntryPerBusPatch);
2022 fIsMuchNoisy = false;
2023 if(AliHLTInt32_t(header->fLength)> maxEntryPerBusPatch[fBusPatchId])
2024 fIsMuchNoisy = true;
2028 void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool parityError)
2030 //function to arrange the decoded Raw Data
2032 if (fSkipParityErrors and parityError) return;
2034 if(fIsMuchNoisy) return;
2036 fIdManuChannel = 0x0;
2037 fIdManuChannel = (fIdManuChannel|fBusPatchId)<<17;
2038 fIdManuChannel |= (dataWord >> 12) & 0x1FFFF;
2040 IdManuChannelToEntry& idToEntry = * const_cast<IdManuChannelToEntry*>(fkIdToEntry);
2041 fLutEntry = idToEntry[fIdManuChannel];
2044 HLTDebug("Failed to find a valid LUT entry.");
2047 fPadCharge = int(((unsigned short)(dataWord & 0xFFF)) - fkLookUpTableData[fLutEntry].fPed);
2050 if(fPadCharge > 2.0*fkLookUpTableData[fLutEntry].fSigma){ // (charge > 4) is due cut out the noise level
2052 fPadData[fDataCount].fDetElemId = fkLookUpTableData[fLutEntry].fDetElemId;
2053 fPadData[fDataCount].fIX = fkLookUpTableData[fLutEntry].fIX;
2054 fPadData[fDataCount].fIY = fkLookUpTableData[fLutEntry].fIY;
2055 fPadData[fDataCount].fRealX = fkLookUpTableData[fLutEntry].fRealX;
2056 fPadData[fDataCount].fRealY = fkLookUpTableData[fLutEntry].fRealY;
2057 fPadData[fDataCount].fRealZ = fkLookUpTableData[fLutEntry].fRealZ;
2058 fPadData[fDataCount].fHalfPadSize = fkLookUpTableData[fLutEntry].fHalfPadSize;
2059 fPadData[fDataCount].fPadSizeXY = fkLookUpTableData[fLutEntry].fPadSizeXY;
2060 fPadData[fDataCount].fPlane = fkLookUpTableData[fLutEntry].fPlane;
2061 fPadData[fDataCount].fBusPatch = fBusPatchId;
2062 fPadData[fDataCount].fRawData = dataWord;
2064 if ( fPadCharge < fkLookUpTableData[fLutEntry].fThres ) {
2065 fCharge = (fkLookUpTableData[fLutEntry].fA0)*fPadCharge;
2067 fCharge = (fkLookUpTableData[fLutEntry].fA0)*(fkLookUpTableData[fLutEntry].fThres)
2068 + (fkLookUpTableData[fLutEntry].fA0)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres)
2069 + (fkLookUpTableData[fLutEntry].fA1)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres)*(fPadCharge-fkLookUpTableData[fLutEntry].fThres);
2072 fPadData[fDataCount].fCharge = fCharge;
2074 if(fkLookUpTableData[fLutEntry].fDetElemId/100 == 6){
2075 fDataCountListPerDetElem[
2076 ((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL)
2077 + GetkNofDetElemInDDL(fDDL)/2)
2079 [fNofDataInDetElem[((fkLookUpTableData[fLutEntry].fDetElemId-(GetkMinDetElemIdInDDL(fDDL)+100))%GetkNofDetElemInDDL(fDDL)
2080 + GetkNofDetElemInDDL(fDDL)/2)
2083 fDataCountListPerDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]
2084 [fNofDataInDetElem[(fkLookUpTableData[fLutEntry].fDetElemId-GetkMinDetElemIdInDDL(fDDL))%GetkNofDetElemInDDL(fDDL)]++] = fDataCount;
2087 // if(fkLookUpTableData[fLutEntry].fDetElemId != fPrevDetElemId){
2088 // if((*fNofFiredDetElem)>0){
2089 // fMaxFiredPerDetElem[(*fNofFiredDetElem)-1] = fDataCount;
2092 // HLTDebug("detElem : %d, prevDetElem : %d, datacount : %d, maxFiredPerDetElem[%d] : %d",
2093 // fkLookUpTableData[fLutEntry].fDetElemId,fPrevDetElemId,fDataCount,
2094 // ((*fNofFiredDetElem)-1),fMaxFiredPerDetElem[(*fNofFiredDetElem)-1]
2097 // (*fNofFiredDetElem)++;
2098 // fPrevDetElemId = fkLookUpTableData[fLutEntry].fDetElemId ;
2101 //if(fPadData[fDataCount].fDetElemId==102)
2103 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",
2104 fkLookUpTableData,fLutEntry,fIdManuChannel,fDDL,
2105 fBusPatchId,fPadData[fDataCount].fDetElemId,fPadData[fDataCount].fPlane,
2106 ((dataWord >> 18) & 0x7FF),((dataWord >> 12) & 0x3F),
2107 fPadData[fDataCount].fIX,fPadData[fDataCount].fIY,
2108 fPadData[fDataCount].fRealX,fPadData[fDataCount].fRealY,fPadData[fDataCount].fRealZ,
2109 (dataWord & 0xFFF),fPadData[fDataCount].fCharge,fkLookUpTableData[fLutEntry].fPed,fkLookUpTableData[fLutEntry].fSigma,
2110 fkLookUpTableData[fLutEntry].fHalfPadSize);
2112 // 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",
2113 // fkLookUpTableData,fLutEntry,fBusPatchId,fPadData[fDataCount].fDetElemId,
2114 // fIdManuChannel,((dataWord >> 18) & 0x7FF),((dataWord >> 12) & 0x3F),
2115 // fPadData[fDataCount].fIX,fPadData[fDataCount].fIY,
2116 // fPadData[fDataCount].fRealX,fPadData[fDataCount].fRealY,fPadData[fDataCount].fRealZ,
2117 // fPadData[fDataCount].fCharge,fkLookUpTableData[fLutEntry].fHalfPadSize,fPadData[fDataCount].fPlane,fkLookUpTableData[fLutEntry].fPed,fkLookUpTableData[fLutEntry].fSigma);
2120 }// if charge is more than DC Cut limit condition