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