]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/MUON/OnlineAnalysis/AliHLTMUONHitReconstructor.cxx
Adding extra options to the hit reconstructor component to better control recovery...
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONHitReconstructor.cxx
CommitLineData
b12fe461 1/**************************************************************************
960d54ad 2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
b12fe461 4 * *
960d54ad 5 * Primary Authors: *
6 * Indranil Das <indra.das@saha.ac.in> *
b12fe461 7 * *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
960d54ad 13 * about the suitability of this software for any purpose. It is *
b12fe461 14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17/* $Id$ */
18
19///////////////////////////////////////////////
20//Author : Indranil Das, SINP, INDIA
21// Sukalyan Chattopadhyay, SINP, INDIA
22//
b12fe461 23//Email : indra.das@saha.ac.in
24// sukalyan.chattopadhyay@saha.ac.in
baff881d 25//
26// This class implements a hit reconstruction algorithm for the dimuon
27// high level trigger.
28// The algorithm finds 3 pad clusters by looking for unique pads with a charge
29// above a certain threshold. A centre of gravity type calculation is applied
30// to the three pads forming the cluster to find the hit's X or Y coordinate
31// along the non-bending and bending planes individually.
32// The sepperate X and Y coordinates are then merged to give the full coordinate
33// of the hit.
34/////////////////////////////////////////////////
b12fe461 35
5c561c5b 36#include "AliHLTMUONHitReconstructor.h"
baff881d 37#include "AliHLTMUONRecHitsBlockStruct.h"
a090ff22 38#include "AliHLTMUONUtils.h"
13f09bc1 39#include <cstring>
84ab1541 40#include <strings.h>
b12fe461 41
42
ee3678d3 43const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDetectorId = 0xA00;
44const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLOffSet = 12;
45const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkNofDDL = 8;
46const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkDDLHeaderSize = 8;
47const AliHLTInt32_t AliHLTMUONHitReconstructor::fgkLutLine = 59648 + 1;
48
49
50AliHLTMUONHitReconstructor::AliHLTMUONHitReconstructor() :
51 AliHLTLogging(),
52 fHLTMUONDecoder(),
53 fkBlockHeaderSize(8),
54 fkDspHeaderSize(8),
55 fkBuspatchHeaderSize(4),
ffc1a6f6 56 fDCCut(-1),
ee3678d3 57 fPadData(NULL),
58 fLookUpTableData(NULL),
59 fRecPoints(NULL),
60 fRecPointsCount(NULL),
61 fMaxRecPointsCount(0),
62 fCentralCountB(0),
63 fCentralCountNB(0),
ee3678d3 64 fDigitPerDDL(0),
65 fCentralChargeB(NULL),
66 fCentralChargeNB(NULL),
67 fRecX(NULL),
68 fRecY(NULL),
69 fAvgChargeX(NULL),
70 fAvgChargeY(NULL),
71 fNofBChannel(NULL),
72 fNofNBChannel(NULL),
73 fNofFiredDetElem(0),
a9afae73 74 fIdToEntry(),
75 fRecoveryMode(kDontTryRecover)
b12fe461 76{
ee3678d3 77 /// Default constructor
78
79 fkBlockHeaderSize = 8;
80 fkDspHeaderSize = 8;
81 fkBuspatchHeaderSize = 4;
82
83 try
84 {
85 fPadData = new AliHLTMUONPad[fgkLutLine];
86 }
87 catch (const std::bad_alloc&)
88 {
878cb83d 89 HLTError("Dynamic memory allocation failed for fPadData in constructor.");
ee3678d3 90 throw;
91 }
92
93 fPadData[0].fDetElemId = 0;
94 fPadData[0].fIX = 0 ;
95 fPadData[0].fIY = 0 ;
96 fPadData[0].fRealX = 0.0 ;
97 fPadData[0].fRealY = 0.0 ;
98 fPadData[0].fRealZ = 0.0 ;
99 fPadData[0].fHalfPadSize = 0.0 ;
100 fPadData[0].fPlane = -1 ;
101 fPadData[0].fCharge = 0 ;
102
103 bzero(fGetIdTotalData, 336*237*2*sizeof(int));
b12fe461 104}
105
106
b12fe461 107AliHLTMUONHitReconstructor::~AliHLTMUONHitReconstructor()
108{
ee3678d3 109 /// Default destructor
110
93a75941 111 if (fPadData)
ee3678d3 112 {
113 delete [] fPadData;
114 fPadData = NULL;
115 }
b12fe461 116}
117
b12fe461 118
93a75941 119void AliHLTMUONHitReconstructor::SetLookUpTable(
120 const AliHLTMUONHitRecoLutRow* lookupTable,
121 const IdManuChannelToEntry* idToEntry
122 )
b12fe461 123{
93a75941 124 /// Sets the Lookup table (LUT) containing the position of each pad with
125 /// electronic channel associated with it. Also the appropriate manu
126 /// channel ID mapping to LUT row is also set.
b12fe461 127
93a75941 128 assert( lookupTable != NULL );
129 assert( idToEntry != NULL );
130
131 fIdToEntry = idToEntry;
132 fLookUpTableData = lookupTable;
b12fe461 133}
134
135
a9afae73 136void AliHLTMUONHitReconstructor::TryRecover(ERecoveryMode mode)
a5d4696f 137{
138 /// Sets if the decoder should enable the error recovery logic.
139
a9afae73 140 // Here we setup the various flags to control exactly how the DDL raw data
141 // decoder will behave and what output is generated during errors.
142 fRecoveryMode = mode;
143 switch (mode)
144 {
145 case kRecoverFull:
146 fHLTMUONDecoder.TryRecover(true);
147 fHLTMUONDecoder.ExitOnError(false);
148 fHLTMUONDecoder.GetHandler().WarnOnly(true);
149 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
150 break;
151 case kRecoverJustSkip:
152 fHLTMUONDecoder.TryRecover(false);
153 fHLTMUONDecoder.ExitOnError(false);
154 fHLTMUONDecoder.GetHandler().WarnOnly(true);
155 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
156 break;
157 case kRecoverFromParityErrorsOnly:
158 fHLTMUONDecoder.TryRecover(false);
159 fHLTMUONDecoder.ExitOnError(false);
160 fHLTMUONDecoder.GetHandler().WarnOnly(false);
161 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(true);
162 break;
163 default:
164 fRecoveryMode = kDontTryRecover;
165 fHLTMUONDecoder.TryRecover(false);
166 fHLTMUONDecoder.ExitOnError(true);
167 fHLTMUONDecoder.GetHandler().WarnOnly(false);
168 fHLTMUONDecoder.GetHandler().PrintParityErrorAsWarning(false);
169 break;
170 }
a5d4696f 171}
172
173
29486e5a 174bool AliHLTMUONHitReconstructor::Run(
175 const AliHLTUInt32_t* rawData,
176 AliHLTUInt32_t rawDataSize,
177 AliHLTMUONRecHitStruct* recHit,
178 AliHLTUInt32_t& nofHit
179 )
180{
b12fe461 181 // main function called by HLTReconstructor to perform DHLT Hitreconstruction
182
29486e5a 183 fRecPoints = recHit;
184 fMaxRecPointsCount = nofHit;
185 fRecPointsCount = &nofHit;
b12fe461 186 *fRecPointsCount = 0;
ee3678d3 187 fDigitPerDDL = 0;
b12fe461 188
ee3678d3 189 if (not DecodeDDL(rawData, rawDataSize)) {
190 // Dont need to log any message again. Already done so in DecodeDDL.
b12fe461 191 return false;
192 }
ee3678d3 193
194 if (fDigitPerDDL == 1)
13f09bc1 195 {
196 // There are no digits to process so stop here.
197 return true;
198 }
b12fe461 199
13f09bc1 200 if (not FindRecHits()) {
960d54ad 201 HLTError("Failed to generate RecHits");
b12fe461 202 return false;
203 }
ee3678d3 204
b12fe461 205 return true;
206}
207
208
ee3678d3 209bool AliHLTMUONHitReconstructor::DecodeDDL(const AliHLTUInt32_t* rawData,AliHLTUInt32_t rawDataSize)
b12fe461 210{
ee3678d3 211 //function to decode Raw Data
212
213 AliHLTMUONRawDecoder& handler = reinterpret_cast<AliHLTMUONRawDecoder&>(fHLTMUONDecoder.GetHandler());
214 UInt_t bufferSize = UInt_t(rawDataSize*sizeof(AliHLTUInt32_t));
215
216 handler.SetDCCut(fDCCut);
217 handler.SetPadData(fPadData);
218 handler.SetLookUpTable(fLookUpTableData);
219 handler.SetIdManuChannelToEntry(fIdToEntry);
220 handler.SetNofFiredDetElemId(fNofFiredDetElem);
221 handler.SetMaxFiredPerDetElem(fMaxFiredPerDetElem);
222
223 if(!fHLTMUONDecoder.Decode(rawData,bufferSize))
a5d4696f 224 {
a9afae73 225 switch (TryRecover())
a5d4696f 226 {
a9afae73 227 case kRecoverFull:
a5d4696f 228 HLTWarning("There was a problem with the raw data."
229 " Recovered as much data as possible."
a9afae73 230 " Will continue processing the next event."
a5d4696f 231 );
a9afae73 232 break;
233 case kRecoverJustSkip:
234 HLTWarning("There was a problem with the raw data."
235 " Skipped corrupted data structures."
236 " Will continue processing the next event."
237 );
238 break;
239 case kRecoverFromParityErrorsOnly:
240 if (fHLTMUONDecoder.GetHandler().NonParityErrorFound())
241 {
242 HLTError("Failed to decode the tracker DDL raw data.");
243 return false;
244 }
245 HLTWarning("Found parity errors in the raw data,"
246 " but will continue processing."
247 );
248 break;
249 default:
250 HLTError("Failed to decode the tracker DDL raw data.");
a5d4696f 251 return false;
252 }
253 }
960d54ad 254
ee3678d3 255 fDigitPerDDL = handler.GetDataCount();
256 fMaxFiredPerDetElem[fNofFiredDetElem-1] = handler.GetDataCount();
90af8855 257
258 HLTDebug("fNofFiredDetElem : %d, NofDigits %d and max reco point limit is : %d, nofDetElems : %d",
259 fNofFiredDetElem,fDigitPerDDL,fMaxRecPointsCount,fNofFiredDetElem);
260
261 for(int iDet=0; iDet<TMath::Max(fNofFiredDetElem,130); iDet++)
262 HLTDebug("NofCount (fMaxFiredPerDetElem) in iDet %d is : %d", iDet, fMaxFiredPerDetElem[iDet]);
263
264 if(fNofFiredDetElem>129){
265 HLTError("Number of fired detection elements is %d, which is more than 129.", fNofFiredDetElem);
266 return false;
267 }
268
ee3678d3 269 if(fDigitPerDDL == 1){
90af8855 270 HLTDebug("An Empty DDL file was found.");
13f09bc1 271 }
90af8855 272
b12fe461 273 return true;
b12fe461 274}
275
960d54ad 276
ee3678d3 277bool AliHLTMUONHitReconstructor::FindRecHits()
b12fe461 278{
878cb83d 279 // fuction that calls hit reconstruction detector element-wise.
280
281 assert( fCentralChargeB == NULL );
282 assert( fCentralChargeNB == NULL );
283 assert( fRecX == NULL );
284 assert( fRecY == NULL );
285 assert( fAvgChargeX == NULL );
286 assert( fAvgChargeY == NULL );
287 assert( fNofBChannel == NULL );
288 assert( fNofNBChannel == NULL );
289
290 bool resultOk = false;
90af8855 291
292 HLTDebug("Number of fired detection elements = %d.", fNofFiredDetElem);
b12fe461 293
878cb83d 294 for(int iDet=0; iDet<fNofFiredDetElem ; iDet++)
295 {
296 fCentralCountB = 0;
297 fCentralCountNB = 0;
ee3678d3 298
878cb83d 299 try
300 {
ee3678d3 301 fCentralChargeB = new int[fMaxFiredPerDetElem[iDet]];
878cb83d 302 HLTDebug("Allocated fCentralChargeB with %d elements.", fMaxFiredPerDetElem[iDet]);
ee3678d3 303 fCentralChargeNB = new int[fMaxFiredPerDetElem[iDet]];
878cb83d 304 HLTDebug("Allocated fCentralChargeNB with %d elements.", fMaxFiredPerDetElem[iDet]);
305 resultOk = true;
ee3678d3 306 }
878cb83d 307 catch(const std::bad_alloc&)
308 {
309 HLTError("Dynamic memory allocation failed for fCentralChargeNB and fCentralChargeB");
310 resultOk = false;
90af8855 311 //break; Do not break. Might have smaller memory requirements in the next iteration.
ee3678d3 312 }
313
878cb83d 314 // Continue processing, but check if everything is OK as we do, otherwise
315 // do not execute the next steps.
316 if (resultOk)
317 {
318 if(iDet>0)
90af8855 319 {
320 HLTDebug("Finding central hists from fMaxFiredPerDetElem[%d] : %d, to fMaxFiredPerDetElem[%d] : %d.",
321 iDet-1, fMaxFiredPerDetElem[iDet-1], iDet, fMaxFiredPerDetElem[iDet]
322 );
878cb83d 323 FindCentralHits(fMaxFiredPerDetElem[iDet-1],fMaxFiredPerDetElem[iDet]);
90af8855 324 }
878cb83d 325 else
90af8855 326 {
327 HLTDebug("Finding central hists from fMaxFiredPerDetElem[1] : %d, to fMaxFiredPerDetElem[%d] : %d.",
328 fMaxFiredPerDetElem[1], iDet, fMaxFiredPerDetElem[iDet]
329 );
878cb83d 330 // minimum value is 1 because dataCount in ReadDDL starts from 1 instead of 0;
331 FindCentralHits(1,fMaxFiredPerDetElem[iDet]);
90af8855 332 }
333
334 HLTDebug("Found fCentralCountB : %d, fCentralCountNB : %d",fCentralCountB,fCentralCountNB);
335 if(fCentralCountB==0 or fCentralCountNB==0)
336 {
337 HLTDebug("There is no fired pad in bending/nonbending plane...skipping this detection element");
338 if (fCentralChargeB != NULL)
339 {
340 delete [] fCentralChargeB;
341 HLTDebug("Released fCentralChargeB array.");
342 fCentralChargeB = NULL;
343 }
344 if (fCentralChargeNB != NULL)
345 {
346 delete [] fCentralChargeNB;
347 HLTDebug("Released fCentralChargeNB array.");
348 fCentralChargeNB = NULL;
349 }
350 continue;
351 }
352 }
878cb83d 353
90af8855 354 if (resultOk)
355 {
878cb83d 356 try
357 {
358 fRecY = new float[fCentralCountB];
359 HLTDebug("Allocated fRecY with %d elements.", fCentralCountB);
360 fRecX = new float[fCentralCountNB];
361 HLTDebug("Allocated fRecX with %d elements.", fCentralCountNB);
362 fAvgChargeY = new float[fCentralCountB];
363 HLTDebug("Allocated fAvgChargeY with %d elements.", fCentralCountB);
364 fAvgChargeX = new float[fCentralCountNB];
365 HLTDebug("Allocated fAvgChargeX with %d elements.", fCentralCountNB);
366 fNofBChannel = new int[fCentralCountB];
367 HLTDebug("Allocated fNofBChannel with %d elements.", fCentralCountB);
368 fNofNBChannel = new int[fCentralCountNB];
369 HLTDebug("Allocated fNofNBChannel with %d elements.", fCentralCountNB);
370 resultOk = true;
371 }
372 catch(const std::bad_alloc&){
373 HLTError("Dynamic memory allocation failed for internal arrays.");
374 resultOk = false;
90af8855 375 //break; Must not break, this will prevent calling delete and memory cleanup, i.e. memory leak.
878cb83d 376 }
ee3678d3 377 }
378
878cb83d 379 if (resultOk) RecXRecY();
380 if (resultOk)
381 {
382 resultOk = MergeRecHits();
383 }
90af8855 384
385 if(iDet==0)
878cb83d 386 {
90af8855 387 // minimum value in loop is 1 because dataCount in ReadDDL starts from 1 instead of 0;
388 for(int i=1;i<fMaxFiredPerDetElem[iDet];i++)
389 fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
390 }
391 else
392 {
393 for(int i=fMaxFiredPerDetElem[iDet-1];i<fMaxFiredPerDetElem[iDet];i++)
394 fGetIdTotalData[fPadData[i].fIX][fPadData[i].fIY][fPadData[i].fPlane] = 0;
b12fe461 395 }
ee3678d3 396
878cb83d 397 // Make sure to release any memory that was allocated.
398 if (fCentralChargeB != NULL)
399 {
400 delete [] fCentralChargeB;
401 HLTDebug("Released fCentralChargeB array.");
13f09bc1 402 fCentralChargeB = NULL;
403 }
878cb83d 404 if (fCentralChargeNB != NULL)
405 {
406 delete [] fCentralChargeNB;
407 HLTDebug("Released fCentralChargeNB array.");
13f09bc1 408 fCentralChargeNB = NULL;
409 }
878cb83d 410 if (fRecX != NULL)
411 {
412 delete [] fRecX;
413 HLTDebug("Released fRecX array.");
414 fRecX = NULL;
415 }
416 if (fRecY != NULL)
417 {
418 delete [] fRecY;
419 HLTDebug("Released fRecY array.");
420 fRecY = NULL;
421 }
422 if (fAvgChargeX != NULL)
423 {
424 delete [] fAvgChargeX;
425 HLTDebug("Released fAvgChargeX array.");
426 fAvgChargeX = NULL;
427 }
428 if (fAvgChargeY != NULL)
429 {
430 delete [] fAvgChargeY;
431 HLTDebug("Released fAvgChargeY array.");
432 fAvgChargeY = NULL;
433 }
434 if (fNofBChannel != NULL)
435 {
436 delete [] fNofBChannel;
437 HLTDebug("Released fNofBChannel array.");
438 fNofBChannel = NULL;
439 }
440 if (fNofNBChannel != NULL)
441 {
442 delete [] fNofNBChannel;
443 HLTDebug("Released fNofNBChannel array.");
444 fNofNBChannel = NULL;
445 }
b12fe461 446 }
ee3678d3 447
878cb83d 448 Clear(); // clear internal arrays.
b12fe461 449
878cb83d 450 return resultOk;
b12fe461 451}
452
960d54ad 453
b12fe461 454void AliHLTMUONHitReconstructor::FindCentralHits(int minPadId, int maxPadId)
455{
456 // to find central hit associated with each cluster
457
878cb83d 458 assert( fCentralChargeB != NULL );
459 assert( fCentralChargeNB != NULL );
460
b12fe461 461 int b,nb;
462 int idManuChannelCentral;
463 bool hasFind;
ee3678d3 464
b12fe461 465 for(int iPad=minPadId;iPad<maxPadId;iPad++){
ee3678d3 466
467 fGetIdTotalData[fPadData[iPad].fIX]
468 [fPadData[iPad].fIY]
469 [fPadData[iPad].fPlane] = iPad ;
b12fe461 470
ee3678d3 471 if(fPadData[iPad].fPlane == 0 ){//&& fPadData[iPad].fIY > (0+1) && fPadData[iPad].fIY < (79 - 1)){
472 //if(fPadData[iPad].fIY > 0){
b12fe461 473 if(fCentralCountB>0){
474 hasFind = false;
475 for(b = 0;b<fCentralCountB;b++){
476 idManuChannelCentral = fCentralChargeB[b];
ee3678d3 477 if(fPadData[iPad].fIX == fPadData[idManuChannelCentral].fIX
b12fe461 478 &&
ee3678d3 479 (fPadData[iPad].fIY
b12fe461 480 == fPadData[idManuChannelCentral].fIY + 1
481 ||
ee3678d3 482 fPadData[iPad].fIY
b12fe461 483 == fPadData[idManuChannelCentral].fIY + 2
484 ||
ee3678d3 485 fPadData[iPad].fIY
b12fe461 486 == fPadData[idManuChannelCentral].fIY - 2
487 ||
ee3678d3 488 fPadData[iPad].fIY
b12fe461 489 == fPadData[idManuChannelCentral].fIY - 1)){
490
491 hasFind = true;
ee3678d3 492 if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
493 fCentralChargeB[b] = iPad;
b12fe461 494 }// if condn on pad charge
495 }// if condon on pad position
496 }// for loop over b
497 if(!hasFind){
ee3678d3 498 fCentralChargeB[fCentralCountB] = iPad;
b12fe461 499 fCentralCountB++;
500 }
501 }
502 else{
ee3678d3 503 fCentralChargeB[fCentralCountB] = iPad;
b12fe461 504 fCentralCountB++;
505 }// check the size of centralHitB
506 for(b = 0;b<fCentralCountB;b++){
507 idManuChannelCentral = fCentralChargeB[b];
508 }
509 //}// if cond on iY > 2 (to avoid edge value pb)
510 }// B/Nb checking
511 else{
512 if(fCentralCountNB>0){
513 hasFind = false;
514 for(nb = 0;nb<fCentralCountNB;nb++){
515 idManuChannelCentral = fCentralChargeNB[nb];
ee3678d3 516 if(fPadData[iPad].fIY == fPadData[idManuChannelCentral].fIY
b12fe461 517 &&
ee3678d3 518 (fPadData[iPad].fIX
b12fe461 519 == fPadData[idManuChannelCentral].fIX + 1
520 ||
ee3678d3 521 fPadData[iPad].fIX
b12fe461 522 == fPadData[idManuChannelCentral].fIX + 2
523 ||
ee3678d3 524 fPadData[iPad].fIX
b12fe461 525 == fPadData[idManuChannelCentral].fIX - 2
526 ||
ee3678d3 527 fPadData[iPad].fIX
b12fe461 528 == fPadData[idManuChannelCentral].fIX - 1)){
529
530 hasFind = true;
ee3678d3 531 if(fPadData[iPad].fCharge > fPadData[idManuChannelCentral].fCharge){
532 fCentralChargeNB[nb] = iPad;
b12fe461 533 }// if condn over to find higher charge
534 }// if condn over to find position
535 }// for loop over presently all nb values
536 if(!hasFind){
ee3678d3 537 fCentralChargeNB[fCentralCountNB] = iPad;
b12fe461 538 fCentralCountNB++;
539 }
540 }// centralHitNB size test
541 else{
ee3678d3 542 fCentralChargeNB[fCentralCountNB] = iPad;
b12fe461 543 fCentralCountNB++;
544 }// centralHitNB size test
545
546 }// fill for bending and nonbending hit
547 }// detElemId loop
ee3678d3 548
b12fe461 549}
550
960d54ad 551
878cb83d 552void AliHLTMUONHitReconstructor::RecXRecY()
b12fe461 553{
554 // find reconstructed X and Y for each plane separately
878cb83d 555
556 assert( fRecX != NULL );
557 assert( fRecY != NULL );
558 assert( fAvgChargeX != NULL );
559 assert( fAvgChargeY != NULL );
560 assert( fNofBChannel != NULL );
561 assert( fNofNBChannel != NULL );
562
b12fe461 563 int b,nb;
564 int idCentral;
565 int idLower = 0;
566 int idUpper = 0;
567 int idRight = 0;
568 int idLeft = 0;
ee3678d3 569
b12fe461 570 for(b=0;b<fCentralCountB;b++){
571 idCentral = fCentralChargeB[b];
ee3678d3 572
b12fe461 573 if(fPadData[idCentral].fIY==0)
574 idLower = 0;
575 else
576 idLower = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY-1][0];
ee3678d3 577
578 if(fPadData[idCentral].fIX==236)
b12fe461 579 idUpper = 0;
580 else
581 idUpper = fGetIdTotalData[fPadData[idCentral].fIX][fPadData[idCentral].fIY+1][0];
582
ee3678d3 583
b12fe461 584 fRecY[b] = (fPadData[idCentral].fRealY*fPadData[idCentral].fCharge
585 +
ee3678d3 586 fPadData[idUpper].fRealY*fPadData[idUpper].fCharge
b12fe461 587 +
ee3678d3 588 fPadData[idLower].fRealY*fPadData[idLower].fCharge
589 )/(fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge) ;
590
591 fAvgChargeY[b] = (fPadData[idCentral].fCharge + fPadData[idUpper].fCharge + fPadData[idLower].fCharge)/3.0 ;
592
593 fNofBChannel[b] = 0;
594 if(fPadData[idLower].fCharge>0)
595 fNofBChannel[b]++ ;
596 if(fPadData[idCentral].fCharge>0)
597 fNofBChannel[b]++ ;
598 if(fPadData[idUpper].fCharge>0)
599 fNofBChannel[b]++ ;
600
90af8855 601 HLTDebug("detelem : %d :--(charge,pos) lower[%d] : (%d,%f), middle[%d] : (%d,%f), upper[%d] : (%d,%f), nofChannel : %d",
602 fPadData[idCentral].fDetElemId,
603 idLower, fPadData[idLower].fCharge, fPadData[idLower].fRealY,
604 idCentral, fPadData[idCentral].fCharge,fPadData[idCentral].fRealY,
605 idUpper, fPadData[idUpper].fCharge, fPadData[idUpper].fRealY,
606 fNofBChannel[b]
607 );
ee3678d3 608
609 HLTDebug("RecY[%d] : %f",b,fRecY[b]);
b12fe461 610 }
611
612 for(nb=0;nb<fCentralCountNB;nb++){
613 idCentral = fCentralChargeNB[nb];
614
615 if(fPadData[idCentral].fIX==0)
616 idLeft = 0;
617 else
618 idLeft = fGetIdTotalData[fPadData[idCentral].fIX-1][fPadData[idCentral].fIY][1];
619
620 if(fPadData[idCentral].fIX==335)
621 idRight = 0 ;
622 else
623 idRight = fGetIdTotalData[fPadData[idCentral].fIX+1][fPadData[idCentral].fIY][1];
624
625 fRecX[nb] = (fPadData[idCentral].fRealX*fPadData[idCentral].fCharge
626 +
627 fPadData[idRight].fRealX*fPadData[idRight].fCharge
628 +
629 fPadData[idLeft].fRealX*fPadData[idLeft].fCharge
630 )/(fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge);
631
632
ee3678d3 633 fAvgChargeX[nb] = (fPadData[idCentral].fCharge + fPadData[idRight].fCharge + fPadData[idLeft].fCharge)/3.0 ;
b12fe461 634
ee3678d3 635
636 fNofNBChannel[nb] = 0;
637 if(fPadData[idLeft].fCharge>0)
638 fNofNBChannel[nb]++ ;
639 if(fPadData[idCentral].fCharge>0)
640 fNofNBChannel[nb]++ ;
641 if(fPadData[idRight].fCharge>0)
642 fNofNBChannel[nb]++ ;
643
90af8855 644 HLTDebug("detelem : %d:--(charge,pos) left[%d] : (%d,%f), middle[%d] : (%d,%f), right[%d] : (%d,%f), nofChannel : %d",
645 fPadData[idLeft].fDetElemId,
646 idLeft, fPadData[idLeft].fCharge, fPadData[idLeft].fRealX,
647 idCentral, fPadData[idCentral].fCharge, fPadData[idCentral].fRealX,
648 idRight, fPadData[idRight].fCharge, fPadData[idRight].fRealX,
649 fNofNBChannel[nb]
650 );
ee3678d3 651
652 HLTDebug("RecX[%d] : %f",nb,fRecX[nb]);
653
b12fe461 654 }
b12fe461 655}
656
960d54ad 657
b12fe461 658bool AliHLTMUONHitReconstructor::MergeRecHits()
659{
660 // Merge reconstructed hits first over same plane then bending plane with non-bending plane
661
878cb83d 662 assert( fRecX != NULL );
663 assert( fRecY != NULL );
664 assert( fAvgChargeX != NULL );
665 assert( fAvgChargeY != NULL );
666 assert( fNofBChannel != NULL );
667 assert( fNofNBChannel != NULL );
668
b12fe461 669 int idCentralB,idCentralNB ;
670 float padCenterXB;
671 float padCenterYNB;
672 float diffX,diffY;
673 float halfPadLengthX,halfPadLengthY;
674
675 // MERGE Bending Plane hits, which are placed side by side
676 for(int i=0;i<fCentralCountB-1;i++){
677 if(fRecY[i] != 0.0){
678 for(int j=i+1;j<fCentralCountB;j++){
679
680 if(fCentralChargeB[i]==fCentralChargeB[j]){
681 fRecY[j] = 0.0;
682 continue;
683 }
684 else if(
685 (
686 fPadData[fCentralChargeB[i]].fIY == fPadData[fCentralChargeB[j]].fIY
687 )
688 &&
689 (
690 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX + 1
691 ||
692 fPadData[fCentralChargeB[i]].fIX == fPadData[fCentralChargeB[j]].fIX - 1
693 )
694 &&
695 fRecY[j] != 0.0
696 &&
697 fRecY[i] != 0.0
698 ){
699
700 if(fAvgChargeY[i] > fAvgChargeY[j]){
701 fRecY[i] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
702 )/(fAvgChargeY[i] + fAvgChargeY[j]);
703 fRecY[j] = 0.0;
704 }
705 else{
706 fRecY[j] = (fRecY[i]*fAvgChargeY[i] + fRecY[j]*fAvgChargeY[j]
707 )/(fAvgChargeY[i] + fAvgChargeY[j]);
708 fRecY[i] = 0.0;
709
710 }// search for higher charge
711 }//pad position
712 }//j for loop
713 }//if fRecY[i] != 0.0
714 }// i for loop
b12fe461 715
716 // MERGE Non Bending Plane hits, which are place side by side
717 for(int i=0;i<fCentralCountNB-1;i++){
718 if(fRecX[i] != 0.0){
719 for(int j=i+1;j<fCentralCountNB;j++){
720
721 if(fCentralChargeNB[i]==fCentralChargeNB[j]){
722 fRecX[j] = 0.0;
723 continue;
724 }
725 else if(
726 (
727 fPadData[fCentralChargeNB[i]].fIX == fPadData[fCentralChargeNB[j]].fIX
728 )
729 &&
730 (
731 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY + 1
732 ||
733 fPadData[fCentralChargeNB[i]].fIY == fPadData[fCentralChargeNB[j]].fIY - 1
734 )
735 &&
736 fRecX[j] != 0.0
737 &&
738 fRecX[i] != 0.0
739 ){
740
741 if(fAvgChargeX[i] > fAvgChargeX[j]){
742 fRecX[i] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
743 )/(fAvgChargeX[i] + fAvgChargeX[j]);
744 fRecX[j] = 0.0;
745 }
746 else{
747 fRecX[j] = (fRecX[i]*fAvgChargeX[i] + fRecX[j]*fAvgChargeX[j]
748 )/(fAvgChargeX[i] + fAvgChargeX[j]);
749 fRecX[i] = 0.0;
750 }// search for higher charge
751 }//pad position
752 }//j for loop
753 }//if fRecX[i] != 0.0
754 }// i for loop
755
b12fe461 756 // Merge bending Plane hits with Non Bending
b12fe461 757 for(int b=0;b<fCentralCountB;b++){
758 if(fRecY[b]!=0.0){
759 idCentralB = fCentralChargeB[b];
760 padCenterXB = fPadData[idCentralB].fRealX;
761
ee3678d3 762 halfPadLengthX = fPadData[idCentralB].fIY ;
b12fe461 763
764 for(int nb=0;nb<fCentralCountNB;nb++){
765 if(fRecX[nb]!=0.0){
766 idCentralNB = fCentralChargeNB[nb];
767
768 padCenterYNB = fPadData[idCentralNB].fRealY;
769
ee3678d3 770 halfPadLengthY = fPadData[idCentralNB].fHalfPadSize ;
b12fe461 771
772 if(fabsf(fRecX[nb]) > fabsf(padCenterXB))
773 diffX = fabsf(fRecX[nb]) - fabsf(padCenterXB);
774 else
775 diffX = fabsf(padCenterXB) - fabsf(fRecX[nb]);
776
777 if(fabsf(padCenterYNB)>fabsf(fRecY[b]))
778 diffY = fabsf(padCenterYNB) - fabsf(fRecY[b]);
779 else
780 diffY = fabsf(fRecY[b]) - fabsf(padCenterYNB);
781
782 if(diffX < halfPadLengthX && diffY < halfPadLengthY ){//&& fPadData[idCentralB].fIY != 0){
783
ee3678d3 784 if(fNofBChannel[b]==3)
785 fRecY[b] += 0.025*sin(12.0*(fRecY[b] - fPadData[idCentralB].fRealY)) ;
786
787 fRecX[nb] += 0.075*sin(9.5*(fRecX[nb] - fPadData[idCentralNB].fRealX)) ;
788
29486e5a 789 // First check that we have not overflowed the buffer.
790 if((*fRecPointsCount) == fMaxRecPointsCount){
90af8855 791 HLTError("Number of RecHits (i.e. %d) exceeds the max number of RecHit limit %d."
792 " Output buffer is too small.",
793 (*fRecPointsCount),fMaxRecPointsCount
794 );
29486e5a 795 return false;
796 }
a090ff22 797
798 AliHLTUInt32_t idflags = AliHLTMUONUtils::PackRecHitFlags(
799 (fPadData[idCentralB].fDetElemId / 100) - 1,
800 fPadData[idCentralB].fDetElemId
801 );
802 fRecPoints[(*fRecPointsCount)].fFlags = idflags;
b12fe461 803 fRecPoints[(*fRecPointsCount)].fX = fRecX[nb];
804 fRecPoints[(*fRecPointsCount)].fY = fRecY[b];
805 fRecPoints[(*fRecPointsCount)].fZ = fPadData[idCentralB].fRealZ;
90af8855 806 HLTDebug("Reconstructed hit (X,Y,Z) : (%f,%f,%f)",
807 fRecPoints[(*fRecPointsCount)].fX,
808 fRecPoints[(*fRecPointsCount)].fY,
809 fRecPoints[(*fRecPointsCount)].fZ
810 );
ee3678d3 811// fRecPoints[(*fRecPointsCount)].fXCenter = fPadData[idCentralNB].fRealX;
812// fRecPoints[(*fRecPointsCount)].fYCenter = fPadData[idCentralB].fRealY;
813// fRecPoints[(*fRecPointsCount)].fNofBChannel = fNofBChannel[b];
814// fRecPoints[(*fRecPointsCount)].fNofNBChannel = fNofNBChannel[nb];
815// fRecPoints[(*fRecPointsCount)].fDetElemId = (AliHLTUInt32_t)fPadData[idCentralB].fDetElemId;
b12fe461 816 (*fRecPointsCount)++;
b12fe461 817 }//if lies wihtin 5.0 mm
818 }// condn over fRecX ! = 0.0
819 }// loop over NB side
820 }// condn on fRecY[b] != 0.0
821 }// loop over B side;
822
b12fe461 823 return true;
824}
13f09bc1 825
826
827void AliHLTMUONHitReconstructor::Clear()
828{
878cb83d 829 // function to clear internal arrays.
ee3678d3 830
90af8855 831 HLTDebug("Clearing fPadData and fMaxFiredPerDetElem buffers.");
832
ee3678d3 833 for(int iPad=1;iPad<fDigitPerDDL;iPad++){
834 fGetIdTotalData[fPadData[iPad].fIX][fPadData[iPad].fIY][fPadData[iPad].fPlane] = 0;
835 fPadData[iPad].fDetElemId = 0;
836 fPadData[iPad].fIX = 0 ;
837 fPadData[iPad].fIY = 0 ;
838 fPadData[iPad].fRealX = 0.0 ;
839 fPadData[iPad].fRealY = 0.0 ;
840 fPadData[iPad].fRealZ = 0.0 ;
841 fPadData[iPad].fHalfPadSize = -1 ;
842 fPadData[iPad].fPlane = -1 ;
843 fPadData[iPad].fCharge = 0 ;
13f09bc1 844 }
845
90af8855 846 for(int i=0;i<130;i++)
13f09bc1 847 fMaxFiredPerDetElem[i] = 0;
ee3678d3 848}
849
850
851AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::AliHLTMUONRawDecoder() :
852 fBufferStart(NULL),
a6b16447 853 fBusPatchId(0),
ffc1a6f6 854 fDCCut(-1),
a6b16447 855 fPadData(NULL),
856 fLookUpTableData(NULL),
857 fNofFiredDetElem(NULL),
858 fMaxFiredPerDetElem(NULL),
859 fIdToEntry(),
860 fDataCount(1),
861 fPrevDetElemId(0),
862 fPadCharge(0),
863 fCharge(0.0),
864 fIdManuChannel(0x0),
a5d4696f 865 fLutEntry(0),
a9afae73 866 fWarnOnly(false),
867 fSkipParityErrors(false),
868 fDontPrintParityErrors(false),
869 fPrintParityErrorAsWarning(false),
870 fNonParityErrorFound(false)
ee3678d3 871{
872 // ctor
873}
874
875
876AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::~AliHLTMUONRawDecoder()
877{
878 // dtor
879}
880
93a75941 881
878cb83d 882void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnNewBuffer(const void* buffer, UInt_t /*bufferSize*/)
883{
884 /// Called for every new raw DDL data payload being processed.
885 /// Just clears internal counters.
886 /// \param buffer The pointer to the raw data buffer.
887
888 assert( buffer != NULL );
889 fBufferStart = buffer;
890 // dataCount starts from 1 because the 0-th element of fPadData is used as null value.
891 fDataCount = 1;
892 *fNofFiredDetElem = 0;
893 fPrevDetElemId = 0 ;
a9afae73 894 fNonParityErrorFound = false;
878cb83d 895};
896
897
898void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnError(ErrorCode code, const void* location)
899{
900 /// Called if there was an error detected in the raw DDL data.
901 /// Logs an error message.
902 /// \param code The error code describing the problem.
903 /// \param location A pointer to the location in the raw data buffer
904 /// where the problem was found.
905
a9afae73 906 if (code != kParityError) fNonParityErrorFound = true;
907 if (fDontPrintParityErrors and code == kParityError) return;
908
878cb83d 909 long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
a9afae73 910 if (fWarnOnly or (fPrintParityErrorAsWarning and code == kParityError))
911 {
912 HLTWarning("There is a problem with decoding the raw data."
913 " %s (Error code: %d, at byte %d). Trying to recover from corrupt data.",
914 ErrorCodeToMessage(code), code, bytepos
915 );
916 }
917 else
918 {
919 HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
920 ErrorCodeToMessage(code), code, bytepos
921 );
922 }
878cb83d 923};
924
925
a9afae73 926void AliHLTMUONHitReconstructor::AliHLTMUONRawDecoder::OnData(UInt_t dataWord, bool parityError)
ee3678d3 927{
928 //function to arrange the decoded Raw Data
929
a9afae73 930 if (fSkipParityErrors and parityError) return;
931
ee3678d3 932 fIdManuChannel = 0x0;
933 fIdManuChannel = (fIdManuChannel|fBusPatchId)<<17;
934 fIdManuChannel |= (dataWord >> 12) & 0x1FFFF;
935
93a75941 936 IdManuChannelToEntry& idToEntry = * const_cast<IdManuChannelToEntry*>(fIdToEntry);
937 fLutEntry = idToEntry[fIdManuChannel];
90af8855 938 if(fLutEntry==0)
939 {
940 HLTDebug("Failed to find a valid LUT entry.");
941 return;
942 }
ee3678d3 943 fPadCharge = int(((unsigned short)(dataWord & 0xFFF)) - fLookUpTableData[fLutEntry].fPed);
944
945 fCharge = 0;
946 if(fPadCharge > fDCCut && fPadCharge > 5.0*fLookUpTableData[fLutEntry].fSigma){ // (charge > 4) is due cut out the noise level
947
948 fPadData[fDataCount].fDetElemId = fLookUpTableData[fLutEntry].fDetElemId;
949 fPadData[fDataCount].fIX = fLookUpTableData[fLutEntry].fIX;
950 fPadData[fDataCount].fIY = fLookUpTableData[fLutEntry].fIY;
951 fPadData[fDataCount].fRealX = fLookUpTableData[fLutEntry].fRealX;
952 fPadData[fDataCount].fRealY = fLookUpTableData[fLutEntry].fRealY;
953 fPadData[fDataCount].fRealZ = fLookUpTableData[fLutEntry].fRealZ;
954 fPadData[fDataCount].fHalfPadSize = fLookUpTableData[fLutEntry].fHalfPadSize;
955 fPadData[fDataCount].fPlane = fLookUpTableData[fLutEntry].fPlane;
956
957 if ( fPadCharge < fLookUpTableData[fLutEntry].fThres ) {
958 fCharge = (fLookUpTableData[fLutEntry].fA0)*fPadCharge;
959 }else{
960 fCharge = (fLookUpTableData[fLutEntry].fA0)*(fLookUpTableData[fLutEntry].fThres)
961 + (fLookUpTableData[fLutEntry].fA0)*(fPadCharge-fLookUpTableData[fLutEntry].fThres)
962 + (fLookUpTableData[fLutEntry].fA1)*(fPadCharge-fLookUpTableData[fLutEntry].fThres)*(fPadCharge-fLookUpTableData[fLutEntry].fThres);
963 }
964
965 fPadData[fDataCount].fCharge = fCharge;
966
967 if(fLookUpTableData[fLutEntry].fDetElemId != fPrevDetElemId){
968 if((*fNofFiredDetElem)>0){
969 fMaxFiredPerDetElem[(*fNofFiredDetElem)-1] = fDataCount;
970 }
90af8855 971
972 HLTDebug("detElem : %d, prevDetElem : %d, datacount : %d, maxFiredPerDetElem[%d] : %d",
973 fLookUpTableData[fLutEntry].fDetElemId,fPrevDetElemId,fDataCount,
974 ((*fNofFiredDetElem)-1),fMaxFiredPerDetElem[(*fNofFiredDetElem)-1]
975 );
976
ee3678d3 977 (*fNofFiredDetElem)++;
978 fPrevDetElemId = fLookUpTableData[fLutEntry].fDetElemId ;
979 }
980
90af8855 981 HLTDebug("LUT address: %p, lutEntry : %d, buspatch : %d, detElem : %d, id : %d, manu : %d,"
982 " channel : %d, iX : %d, iY: %d, (X,Y) : (%f, %f), charge : %d, padsize : %f, plane : %d",
983 fLookUpTableData, fLutEntry, fBusPatchId, fPadData[fDataCount].fDetElemId,
984 fIdManuChannel, ((dataWord >> 18) & 0x7FF), ((dataWord >> 12) & 0x3F),
985 fPadData[fDataCount].fIX, fPadData[fDataCount].fIY,
986 fPadData[fDataCount].fRealX, fPadData[fDataCount].fRealY,
987 fPadData[fDataCount].fCharge, fPadData[fDataCount].fHalfPadSize,
988 fPadData[fDataCount].fPlane
989 );
ee3678d3 990
90af8855 991 fDataCount++;
ee3678d3 992 }// if charge is more than DC Cut limit condition
993
13f09bc1 994}