]>
Commit | Line | Data |
---|---|---|
6efe69e7 | 1 | /************************************************************************** |
b39b98c8 | 2 | * This file is property of and copyright by the ALICE HLT Project * |
6efe69e7 | 3 | * All rights reserved. * |
4 | * * | |
5 | * Primary Authors: * | |
6 | * Indranil Das <indra.das@saha.ac.in> * | |
b39b98c8 | 7 | * Artur Szostak <artursz@iafrica.com> * |
6efe69e7 | 8 | * * |
9 | * Permission to use, copy, modify and distribute this software and its * | |
10 | * documentation strictly for non-commercial purposes is hereby granted * | |
11 | * without fee, provided that the above copyright notice appears in all * | |
12 | * copies and that both the copyright notice and this permission notice * | |
13 | * appear in the supporting documentation. The authors make no claims * | |
b39b98c8 | 14 | * about the suitability of this software for any purpose. It is * |
6efe69e7 | 15 | * provided "as is" without express or implied warranty. * |
16 | **************************************************************************/ | |
17 | ||
1d8ae082 | 18 | // $Id$ |
6efe69e7 | 19 | |
20 | /********************************************************************** | |
21 | Created on : 16/05/2007 | |
b39b98c8 | 22 | Purpose : This class reads the tracker DDL files and gives the output |
23 | as AliMUONTriggerRecordStruct structures. | |
6efe69e7 | 24 | Author : Indranil Das, HEP Division, SINP |
25 | Email : indra.das@saha.ac.in | indra.ehep@gmail.com | |
b39b98c8 | 26 | |
27 | Artur Szostak <artursz@iafrica.com>: | |
28 | Completely reimplemented the lookup table to a simplified format. | |
6efe69e7 | 29 | **********************************************************************/ |
30 | ||
69c14678 | 31 | /// |
32 | /// @file AliHLTMUONTriggerReconstructor.cxx | |
33 | /// @author Indranil Das <indra.das@saha.ac.in>, | |
34 | /// Artur Szostak <artursz@iafrica.com> | |
35 | /// @date 16 May 2007 | |
36 | /// @brief Implementation of the AliHLTMUONTriggerReconstructor class. | |
37 | /// | |
38 | /// The trigger reconstructor class is designed to deal the rawdata inputfiles | |
39 | /// to findout the the reconstructed hits at the trigger DDL. The output is send | |
40 | /// to the output block for further processing. | |
41 | /// | |
6efe69e7 | 42 | |
6efe69e7 | 43 | #include "AliHLTMUONTriggerReconstructor.h" |
c95cf30c | 44 | #include "AliHLTMUONTriggerRecordsBlockStruct.h" |
7af42d4d | 45 | #include "AliHLTMUONUtils.h" |
46 | #include "AliHLTMUONConstants.h" | |
47 | #include "AliHLTMUONCalculations.h" | |
69c14678 | 48 | #include "AliRawDataHeader.h" |
7af42d4d | 49 | #include <vector> |
547f15d6 | 50 | #include <cassert> |
6efe69e7 | 51 | |
960d54ad | 52 | |
80590aa1 | 53 | AliHLTMUONTriggerReconstructor::AliHLTMUONTriggerReconstructor() : |
69c14678 | 54 | AliHLTLogging(), |
55 | fDecoder() | |
56 | { | |
57 | /// Default constructor. | |
58 | } | |
59 | ||
60 | ||
61 | AliHLTMUONTriggerReconstructor::~AliHLTMUONTriggerReconstructor() | |
62 | { | |
63 | /// Default destructor. | |
64 | } | |
65 | ||
66 | ||
67 | bool AliHLTMUONTriggerReconstructor::Run( | |
68 | const AliHLTUInt8_t* rawData, | |
69 | AliHLTUInt32_t rawDataSize, | |
a5d4696f | 70 | bool scalarEvent, |
69c14678 | 71 | AliHLTMUONTriggerRecordStruct* trigRecord, |
a3d4b6ba | 72 | AliHLTUInt32_t& nofTrigRec |
69c14678 | 73 | ) |
74 | { | |
75 | /// Runs the trigger reconstruction algorithm on the raw data. | |
a3d4b6ba | 76 | /// [in] \param rawData Pointer to the raw data DDL payload. |
77 | /// [in] \param rawDataSize Size of the raw data DDL payload in bytes. | |
78 | /// [in] \param scalarEvent Indicates if the raw data should contain | |
79 | /// scalar data also. | |
80 | /// [out] \param trigRecord Pointer to output buffer for reconstructed | |
81 | /// trigger records. | |
82 | /// [in/out] \param nofTrigRec Initialy should indicate the number of | |
83 | /// elements that can be stored in the trigRecord array. It will | |
84 | /// contain the number of elements filled after this method has returned. | |
85 | /// \return true if raw data was decoded and false if there was a problem | |
86 | /// with the raw data or we overflowed the output buffer. | |
87 | /// | |
88 | /// \note OverflowedOutputBuffer() can be used to check if the output | |
89 | /// buffer 'trigRecord' was overflowed during this method call. | |
69c14678 | 90 | |
91 | // Reset and initialise some variables in the decoder. | |
92 | fDecoder.GetHandler().MaxOutputTrigRecs(nofTrigRec); | |
93 | fDecoder.GetHandler().OutputTrigRecs(trigRecord); | |
69c14678 | 94 | |
a5d4696f | 95 | if (not fDecoder.Decode(rawData, rawDataSize, scalarEvent)) |
96 | { | |
97 | if (TryRecover()) | |
98 | { | |
99 | HLTWarning("There was a problem with the raw data." | |
100 | " Recovered as much data as possible." | |
a9afae73 | 101 | " Will continue processing the next event." |
a5d4696f | 102 | ); |
103 | } | |
104 | else | |
105 | { | |
a9afae73 | 106 | HLTError("Failed to decode the trigger DDL raw data."); |
a5d4696f | 107 | return false; |
108 | } | |
109 | } | |
69c14678 | 110 | |
111 | // nofTrigRec now becomes the output of how many trigger records were found. | |
112 | nofTrigRec = fDecoder.GetHandler().OutputTrigRecsCount(); | |
113 | ||
114 | return not fDecoder.GetHandler().OverflowedOutputBuffer(); | |
115 | } | |
116 | ||
117 | ||
a5d4696f | 118 | void AliHLTMUONTriggerReconstructor::TryRecover(bool value) |
119 | { | |
a3d4b6ba | 120 | /// Sets the flag indicating if the decoder should enable the error |
121 | /// recovery logic. | |
a5d4696f | 122 | |
123 | fDecoder.TryRecover(value); | |
124 | fDecoder.ExitOnError(not value); | |
125 | fDecoder.GetHandler().WarnOnly(value); | |
126 | } | |
127 | ||
128 | ||
69c14678 | 129 | AliHLTMUONTriggerReconstructor::AliDecoderHandler::AliDecoderHandler() : |
130 | AliMUONTriggerDDLDecoderEventHandler(), | |
131 | AliHLTLogging(), | |
132 | fLookupTable(), | |
133 | fBufferStart(NULL), | |
134 | fMaxOutputTrigRecs(0), | |
135 | fOutputTrigRecsCount(0), | |
136 | fOutputTrigRecs(NULL), | |
c95cf30c | 137 | fTrigRecId(0), |
406c5bc3 | 138 | fDDLBit(0), |
69c14678 | 139 | fSuppressPartialTriggers(false), |
a5d4696f | 140 | fOverflowed(false), |
a3d4b6ba | 141 | fWarnOnly(false), |
2b7af22a | 142 | fUseLocalId(true), |
a3d4b6ba | 143 | fUseCrateId(true), |
144 | fCurrentCrateId(0), | |
145 | fCurrentRegional(0) | |
6efe69e7 | 146 | { |
a3d4b6ba | 147 | /// Default constructor just resets the lookup table to zero and local |
148 | /// structure marker pointers to NULL. | |
b39b98c8 | 149 | |
a3d4b6ba | 150 | for (AliHLTInt32_t i = 0; i < 16; i++) |
151 | for (AliHLTInt32_t j = 0; j < 16; j++) | |
152 | for (AliHLTInt32_t k = 0; k < 4; k++) | |
153 | for (AliHLTInt32_t n = 0; n < 2; n++) | |
154 | for (AliHLTInt32_t m = 0; m < 16; m++) | |
b39b98c8 | 155 | { |
a090ff22 | 156 | fLookupTable.fRow[i][j][k][n][m].fIdFlags = 0x0; |
c95cf30c | 157 | fLookupTable.fRow[i][j][k][n][m].fX = 0; |
158 | fLookupTable.fRow[i][j][k][n][m].fY = 0; | |
159 | fLookupTable.fRow[i][j][k][n][m].fZ = 0; | |
b39b98c8 | 160 | } |
6efe69e7 | 161 | } |
162 | ||
163 | ||
a3d4b6ba | 164 | bool AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindStripsOnMT1( |
165 | const AliMUONLocalInfoStruct* localStruct, | |
166 | AliHLTInt32_t& xPos, AliHLTInt32_t& yPos | |
167 | ) | |
168 | { | |
169 | /// This method will find the X and Y strip positions on stations MT1 | |
170 | /// of the trigger system which were fired for the corresponding | |
171 | /// L0 local trigger decision. | |
172 | /// [in] \param localStruct The local trigger structure as found in the DDL payload. | |
173 | /// [out] \param xPos The X strip that was fired. | |
174 | /// [out] \param yPos The Y strip that was fired. | |
175 | /// \return true is returned if a strip was fired, otherwise a warning is | |
176 | /// generated and false is returned. | |
177 | ||
178 | // Try to identify the strips on MT1 (chambers 11 or 12) that fired | |
179 | // the trigger and set yPos and xPos to the correct values. | |
180 | // For the Y strips the yPos value might or might not have to be divided | |
181 | // by 2. This depends on the switches in the trigger electronics and how | |
182 | // they were configured. To avoid having to try to track this info we | |
183 | // just use a trial and error method. | |
184 | yPos = GetLocalYPos(localStruct); | |
185 | AliHLTUInt32_t yStrips = GetLocalY1(localStruct); | |
186 | if (((yStrips >> yPos) & 0x1) == 0x1) | |
187 | { | |
188 | // nothing to do, yPos is already correct. | |
189 | } | |
190 | else if (((yStrips >> (yPos + 1)) & 0x1) == 0x1) | |
191 | { | |
192 | yPos = yPos + 1; | |
193 | } | |
194 | else if (((yStrips >> (yPos / 2)) & 0x1) == 0x1) | |
195 | { | |
196 | yPos = yPos / 2; | |
197 | } | |
198 | else if (((yStrips >> (yPos / 2 + 1)) & 0x1) == 0x1) | |
199 | { | |
200 | yPos = yPos / 2 + 1; | |
201 | } | |
202 | else | |
203 | { | |
204 | // OK, move onto chamber 12. | |
205 | yStrips = GetLocalY2(localStruct); | |
206 | if (((yStrips >> (yPos)) & 0x1) == 0x1) | |
207 | { | |
208 | // nothing to do, yPos is already correct. | |
209 | } | |
210 | else if (((yStrips >> (yPos + 1)) & 0x1) == 0x1) | |
211 | { | |
212 | yPos = yPos + 1; | |
213 | } | |
214 | else if (((yStrips >> (yPos / 2)) & 0x1) == 0x1) | |
215 | { | |
216 | yPos = yPos / 2; | |
217 | } | |
218 | else if (((yStrips >> (yPos / 2 + 1)) & 0x1) == 0x1) | |
219 | { | |
220 | yPos = yPos / 2 + 1; | |
221 | } | |
222 | else | |
223 | { | |
224 | // At this point give up on the value of yPos and just | |
225 | // try find the first strip that was fired. | |
226 | yStrips = GetLocalY1(localStruct); | |
227 | for (AliHLTInt32_t i = 0; i < 16; i++) | |
228 | { | |
229 | if (((yStrips >> i) & 0x1) == 0x1) | |
230 | { | |
231 | yPos = i; | |
232 | goto foundYstrip; | |
233 | } | |
234 | } | |
235 | ||
236 | yStrips = GetLocalY2(localStruct); | |
237 | for (AliHLTInt32_t i = 0; i < 16; i++) | |
238 | { | |
239 | if (((yStrips >> i) & 0x1) == 0x1) | |
240 | { | |
241 | yPos = i; | |
242 | goto foundYstrip; | |
243 | } | |
244 | } | |
245 | ||
246 | // No y strip found in MT1 so this local trigger circuit | |
247 | // does not pass the 3/4 coincidence requirement, | |
248 | // so ignore it and continue. | |
249 | HLTWarning("Could not find fired Y strip for local trigger" | |
250 | " structure (regional structure = %d, crate ID = %d, ID = %d)," | |
251 | " which corresponds to triggered strip YPos = %d.", | |
252 | fCurrentRegional, fCurrentCrateId, GetLocalId(localStruct), | |
253 | GetLocalYPos(localStruct) | |
254 | ); | |
255 | return false; | |
256 | ||
257 | foundYstrip: ; | |
258 | } | |
259 | } | |
260 | ||
261 | // Now find the X strip on MT1 that fired the trigger. | |
262 | xPos = GetLocalXPos(localStruct); | |
263 | AliHLTUInt32_t xStrips = GetLocalX1(localStruct); | |
264 | if (((xStrips >> (xPos / 2)) & 0x1) == 0x1) | |
265 | { | |
266 | xPos = xPos / 2; | |
267 | } | |
268 | else if (((xStrips >> (xPos / 2 + 1)) & 0x1) == 0x1) | |
269 | { | |
270 | xPos = xPos / 2 + 1; | |
271 | } | |
272 | else | |
273 | { | |
274 | // OK, move onto chamber 12. | |
275 | xStrips = GetLocalX2(localStruct); | |
276 | if (((xStrips >> (xPos / 2)) & 0x1) == 0x1) | |
277 | { | |
278 | xPos = xPos / 2; | |
279 | } | |
280 | else if (((xStrips >> (xPos / 2 + 1)) & 0x1) == 0x1) | |
281 | { | |
282 | xPos = xPos / 2 + 1; | |
283 | } | |
284 | else | |
285 | { | |
286 | // At this point give up on the value of xPos and just | |
287 | // try find the first strip that was fired. | |
288 | xStrips = GetLocalX1(localStruct); | |
289 | for (AliHLTInt32_t i = 0; i < 16; i++) | |
290 | { | |
291 | if (((xStrips >> i) & 0x1) == 0x1) | |
292 | { | |
293 | xPos = i; | |
294 | goto foundXstrip; | |
295 | } | |
296 | } | |
297 | ||
298 | xStrips = GetLocalX2(localStruct); | |
299 | for (AliHLTInt32_t i = 0; i < 16; i++) | |
300 | { | |
301 | if (((xStrips >> i) & 0x1) == 0x1) | |
302 | { | |
303 | xPos = i; | |
304 | goto foundXstrip; | |
305 | } | |
306 | } | |
307 | ||
308 | // No x strip found in MT1 so this local trigger circuit | |
309 | // does not pass the 3/4 coincidence requirement, | |
310 | // so ignore it and continue. | |
311 | HLTWarning("Could not find fired X strip for local trigger" | |
312 | " structure (regional structure = %d, crate ID = %d, ID = %d)," | |
313 | " which corresponds to triggered strip XPos = %d.", | |
314 | fCurrentRegional, fCurrentCrateId, GetLocalId(localStruct), | |
315 | GetLocalXPos(localStruct) | |
316 | ); | |
317 | return false; | |
318 | ||
319 | foundXstrip: ; | |
320 | } | |
321 | } | |
322 | ||
323 | return true; | |
324 | } | |
325 | ||
326 | ||
327 | void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindXStrips( | |
328 | const AliMUONLocalInfoStruct* localStruct, AliHLTInt32_t startPos, | |
329 | AliHLTInt32_t pos[4] | |
330 | ) | |
331 | { | |
332 | /// Finds the X strips that were fired in the local trigger structure. | |
333 | /// [in] \param localStruct The local trigger structure as found in the DDL payload. | |
334 | /// [in] \param startPos The first X strip location to start looking from. | |
335 | /// [out] \param pos Array of X strip positions on chambers 11 to 14. pos[0] | |
336 | /// is for chamber 11, pos[1] for chamber 12 and so on. | |
337 | /// The elements of the array will contain -1 if no valid strip position | |
338 | /// was found for that chamber. | |
339 | ||
340 | assert( startPos >= 0 ); | |
341 | ||
342 | if (((GetLocalX1(localStruct) >> startPos) & 0x1) == 0x1) | |
343 | { | |
344 | pos[0] = startPos; | |
345 | } | |
346 | else | |
347 | { | |
348 | pos[0] = -1; | |
349 | } | |
350 | ||
351 | AliHLTUInt32_t xStrips = GetLocalX2(localStruct); | |
352 | if (GetLocalSXDev(localStruct)) // check the direction of the deviation. | |
353 | { | |
354 | // For hits on chamber 12 we have to look for fired strips | |
355 | // within 1 strip of startPos. Where startPos is the X position | |
356 | // as found by FindStripsOnMT1. | |
357 | if (((xStrips >> startPos) & 0x1) == 0x1) | |
358 | { | |
359 | pos[1] = startPos; | |
360 | } | |
361 | else if (((xStrips >> (startPos + 1)) & 0x1) == 0x1) | |
362 | { | |
363 | pos[1] = startPos + 1; | |
364 | } | |
365 | else | |
366 | { | |
367 | pos[1] = -1; | |
368 | } | |
369 | ||
370 | // Given the MT1 coordinate and the deviation information we can | |
371 | // identify the X strip on MT2 that corresponds to the L0 trigger. | |
372 | // For fired strips on MT2 we look for strips that are within 2 | |
373 | // strips of the position endPos = (posX + deviation) / 2, where | |
374 | // posX = GetLocalXPos(localStruct); | |
375 | // deviation = GetLocalXDev(localStruct) | |
376 | // We use the 2 strip tollerance because there is a truncation of 1 | |
377 | // bit when we apply integer divide by 2. | |
378 | // This procedure should thus apply the same constraints and | |
379 | // tollerance as the L0 electronics for the X strip 'mini-roads', | |
380 | // ref. section 3.4.2.2, "Technical Design Report of the Dimuon | |
381 | // Forward Spectrometer". | |
382 | AliHLTInt32_t endPos = (GetLocalXPos(localStruct) + GetLocalXDev(localStruct)) / 2; | |
383 | ||
384 | // Note the order of the checks are such that we choose the strip with | |
385 | // giving the smallest deviation. | |
386 | xStrips = GetLocalX3(localStruct); | |
387 | if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1) | |
388 | { | |
389 | pos[2] = endPos; | |
390 | } | |
391 | else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1) | |
392 | { | |
393 | pos[2] = endPos - 1; | |
394 | } | |
395 | else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1) | |
396 | { | |
397 | pos[2] = endPos + 1; | |
398 | } | |
399 | else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1) | |
400 | { | |
401 | pos[2] = endPos - 2; | |
402 | } | |
403 | else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1) | |
404 | { | |
405 | pos[2] = endPos + 2; | |
406 | } | |
407 | else | |
408 | { | |
409 | pos[2] = -1; | |
410 | } | |
411 | ||
412 | xStrips = GetLocalX4(localStruct); | |
413 | if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1) | |
414 | { | |
415 | pos[3] = endPos; | |
416 | } | |
417 | else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1) | |
418 | { | |
419 | pos[3] = endPos - 1; | |
420 | } | |
421 | else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1) | |
422 | { | |
423 | pos[3] = endPos + 1; | |
424 | } | |
425 | else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1) | |
426 | { | |
427 | pos[3] = endPos - 2; | |
428 | } | |
429 | else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1) | |
430 | { | |
431 | pos[3] = endPos + 2; | |
432 | } | |
433 | else | |
434 | { | |
435 | pos[3] = -1; | |
436 | } | |
437 | } | |
438 | else | |
439 | { | |
440 | // The following code is the same as for the | |
441 | // GetLocalSXDev(localStruct) == true case above, but with the | |
442 | // arithmetic changing sign. | |
443 | if (((xStrips >> startPos) & 0x1) == 0x1) | |
444 | { | |
445 | pos[1] = startPos; | |
446 | } | |
447 | else if (startPos - 1 >= 0 and ((xStrips >> (startPos - 1)) & 0x1) == 0x1) | |
448 | { | |
e58860af | 449 | pos[1] = startPos - 1; |
a3d4b6ba | 450 | } |
451 | else | |
452 | { | |
453 | pos[1] = -1; | |
454 | } | |
455 | ||
456 | AliHLTInt32_t endPos = (GetLocalXPos(localStruct) - GetLocalXDev(localStruct)) / 2; | |
457 | ||
458 | xStrips = GetLocalX3(localStruct); | |
459 | if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1) | |
460 | { | |
461 | pos[2] = endPos; | |
462 | } | |
463 | else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1) | |
464 | { | |
465 | pos[2] = endPos + 1; | |
466 | } | |
467 | else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1) | |
468 | { | |
469 | pos[2] = endPos - 1; | |
470 | } | |
471 | else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1) | |
472 | { | |
473 | pos[2] = endPos + 2; | |
474 | } | |
475 | else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1) | |
476 | { | |
477 | pos[2] = endPos - 2; | |
478 | } | |
479 | else | |
480 | { | |
481 | pos[2] = -1; | |
482 | } | |
483 | ||
484 | xStrips = GetLocalX4(localStruct); | |
485 | if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1) | |
486 | { | |
487 | pos[3] = endPos; | |
488 | } | |
489 | else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1) | |
490 | { | |
491 | pos[3] = endPos + 1; | |
492 | } | |
493 | else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1) | |
494 | { | |
495 | pos[3] = endPos - 1; | |
496 | } | |
497 | else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1) | |
498 | { | |
499 | pos[3] = endPos + 2; | |
500 | } | |
501 | else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1) | |
502 | { | |
503 | pos[3] = endPos - 2; | |
504 | } | |
505 | else | |
506 | { | |
507 | pos[3] = -1; | |
508 | } | |
509 | } | |
510 | } | |
511 | ||
512 | ||
513 | void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindYStrips( | |
514 | const AliMUONLocalInfoStruct* localStruct, AliHLTInt32_t startPos, | |
515 | AliHLTInt32_t pos[4] | |
69c14678 | 516 | ) |
6efe69e7 | 517 | { |
a3d4b6ba | 518 | /// Finds the Y strips that were fired in the local trigger structure. |
519 | /// [in] \param localStruct The local trigger structure as found in the DDL payload. | |
520 | /// [in] \param startPos The first Y strip location to start looking from. | |
521 | /// [out] \param pos Array of Y strip positions on chambers 11 to 14. pos[0] | |
522 | /// is for chamber 11, pos[1] for chamber 12 and so on. | |
523 | /// The elements of the array will contain -1 if no valid strip position | |
524 | /// was found for that chamber. | |
69c14678 | 525 | |
a3d4b6ba | 526 | assert( startPos >= 0 ); |
69c14678 | 527 | |
a3d4b6ba | 528 | // First we scan from the i'th = startPos strip upwards (i.e. i+1, i+2 etc..) |
529 | // to find the first fired strip. Then we similarly scan downwards | |
530 | // (i.e. i-1, i-2 etc..) to find the first fired strip. We actually only need | |
531 | // to check in the range [i-1 .. i+1] due to the constraint that valid tracks | |
532 | // only have a +/- 1 Y strip deviation on consecutive chambers. | |
533 | // Ideally we should have all of posUp[i] == posDown[i] == startPos, but this | |
534 | // need not be the case due to multiple scattering. | |
535 | // This procedure should thus apply the same constraints and tollerance | |
536 | // as the L0 electronics for the Y strip 'roads', | |
537 | // ref. section 3.4.2.2, "Technical Design Report of the Dimuon Forward Spectrometer". | |
538 | AliHLTUInt32_t strips[4] = { | |
539 | GetLocalY1(localStruct), GetLocalY2(localStruct), | |
540 | GetLocalY3(localStruct), GetLocalY4(localStruct) | |
541 | }; | |
542 | AliHLTUInt8_t posUpCount = 0, posDownCount = 0; | |
543 | AliHLTInt32_t posUp[4] = {-1, -1, -1, -1}; | |
544 | AliHLTInt32_t posDown[4] = {-1, -1, -1, -1}; | |
545 | for (AliHLTInt32_t n = 0; n < 4; n++) | |
546 | { | |
547 | for (AliHLTInt32_t i = startPos; i <= startPos+1; i++) | |
548 | { | |
549 | if (((strips[n] >> i) & 0x1) == 0x1) | |
550 | { | |
551 | posUp[n] = i; | |
552 | posUpCount++; | |
553 | break; | |
554 | } | |
555 | } | |
556 | for (AliHLTInt32_t i = startPos; i >= 0; i--) | |
557 | { | |
558 | if (((strips[n] >> i) & 0x1) == 0x1) | |
559 | { | |
560 | posDown[n] = i; | |
561 | posDownCount++; | |
562 | break; | |
563 | } | |
564 | } | |
565 | } | |
566 | ||
567 | // Now select either posUp or posDown, whichever has the most found strips. | |
568 | if (posUpCount > posDownCount) | |
569 | { | |
570 | for (AliHLTInt32_t n = 0; n < 4; n++) | |
571 | pos[n] = posUp[n]; | |
572 | } | |
573 | else | |
574 | { | |
575 | for (AliHLTInt32_t n = 0; n < 4; n++) | |
576 | pos[n] = posDown[n]; | |
577 | } | |
6efe69e7 | 578 | } |
579 | ||
6efe69e7 | 580 | |
a3d4b6ba | 581 | void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit( |
582 | AliHLTUInt32_t xStrips, AliHLTUInt32_t yStrips, | |
583 | AliHLTInt32_t xPos, AliHLTInt32_t yPos, | |
584 | AliHLTUInt8_t crateId, AliHLTUInt8_t locId, AliHLTUInt8_t chamber, | |
585 | AliHLTMUONRecHitStruct& hit | |
586 | ) | |
587 | { | |
588 | /// Reconstructs the hit coordinates for the given chamber from the | |
589 | /// strip and fired strip information provided. | |
590 | /// [in] \param xStrips The X strip pattern for the given chamber. | |
591 | /// [in] \param yStrips The Y strip pattern for the given chamber. | |
592 | /// [in] \param xPos The position of the X strip that was fired. | |
593 | /// [in] \param yPos The position of the Y strip that was fired. | |
594 | /// [in] \param chamber The chamber on which the strips were found. | |
595 | /// Valid range [0..3]. | |
596 | /// [out] \param hit This will be filled with the reconstructed hit. | |
597 | ||
598 | assert( 0 <= xPos and xPos < 16 ); | |
599 | assert( 0 <= yPos and yPos < 16 ); | |
600 | assert( ((xStrips >> xPos) & 0x1) == 0x1 ); | |
601 | assert( ((yStrips >> yPos) & 0x1) == 0x1 ); | |
602 | assert( chamber <= 3 ); | |
603 | assert( crateId < 16 ); | |
604 | assert( locId < 16 ); | |
605 | ||
606 | // Decode the Y position of the hit from the strip position information. | |
607 | // If two neighbouring strips were fired then we decluster the strips like | |
608 | // the L0 electronics does by taking the middle position of the two strips. | |
609 | if (xPos > 0 and ((xStrips >> (xPos-1)) & 0x1) == 0x1) | |
610 | { | |
611 | if (((xStrips >> (xPos+1)) & 0x1) == 0x1) | |
612 | { | |
613 | // Strips fired on both sides of strip at xPos so just use the middle one. | |
614 | hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags; | |
615 | hit.fY = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY; | |
616 | hit.fZ = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ; | |
617 | } | |
618 | else | |
619 | { | |
620 | // Second strip fired below the one at xPos, so decluster. | |
621 | assert(xPos-1 < 16); | |
622 | hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags; | |
623 | hit.fY = (fLookupTable.fRow[crateId][locId][chamber][0][xPos-1].fY | |
624 | + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY) * 0.5; | |
625 | hit.fZ = (fLookupTable.fRow[crateId][locId][chamber][0][xPos-1].fZ | |
626 | + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ) * 0.5; | |
627 | } | |
628 | } | |
629 | else | |
630 | { | |
631 | if (((xStrips >> (xPos+1)) & 0x1) == 0x1) | |
632 | { | |
633 | // Second strip fired above the one at xPos, so decluster. | |
634 | assert(xPos+1 < 16); | |
635 | hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags; | |
636 | hit.fY = (fLookupTable.fRow[crateId][locId][chamber][0][xPos+1].fY | |
637 | + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY) * 0.5; | |
638 | hit.fZ = (fLookupTable.fRow[crateId][locId][chamber][0][xPos+1].fZ | |
639 | + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ) * 0.5; | |
640 | } | |
641 | else | |
642 | { | |
643 | // Only strip at xPos fired and neither of its two neighbours. | |
644 | hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags; | |
645 | hit.fY = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY; | |
646 | hit.fZ = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ; | |
647 | } | |
648 | } | |
649 | ||
650 | // Similarly decode the X position of the hit from the strip position information. | |
651 | // Also decluster like for the Y strips. | |
652 | if (yPos > 0 and ((yStrips >> (yPos-1)) & 0x1) == 0x1) | |
653 | { | |
654 | if (((yStrips >> (yPos+1)) & 0x1) == 0x1) | |
655 | { | |
656 | // Strips fired on both sides of strip at yPos so just use the middle one. | |
657 | hit.fX = fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX; | |
658 | } | |
659 | else | |
660 | { | |
661 | // Second strip fired below the one at yPos, so decluster. | |
662 | assert(yPos-1 < 16); | |
663 | hit.fX = (fLookupTable.fRow[crateId][locId][chamber][1][yPos-1].fX | |
664 | + fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX) * 0.5; | |
665 | } | |
666 | } | |
667 | else | |
668 | { | |
669 | if (((yStrips >> (yPos+1)) & 0x1) == 0x1) | |
670 | { | |
671 | // Second strip fired above the one at yPos, so decluster. | |
672 | assert(yPos+1 < 16); | |
673 | hit.fX = (fLookupTable.fRow[crateId][locId][chamber][1][yPos+1].fX | |
674 | + fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX) * 0.5; | |
675 | } | |
676 | else | |
677 | { | |
678 | // Only strip at yPos fired and neither of its two neighbours. | |
679 | hit.fX = fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX; | |
680 | } | |
681 | } | |
682 | } | |
683 | ||
684 | ||
685 | void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2( | |
686 | UInt_t iloc, | |
69c14678 | 687 | const AliMUONLocalInfoStruct* localStruct, |
688 | const AliMUONLocalScalarsStruct* /*scalars*/ | |
227e7192 | 689 | ) |
6efe69e7 | 690 | { |
69c14678 | 691 | /// Converts a local trigger structure from the L0 into a trigger record. |
692 | /// The dHLT trigger records is then used as a seed for tracking algorithms. | |
693 | /// \note fOutputTrigRecs must be set before calling the decoder to decode | |
694 | /// a new raw data buffer. | |
695 | /// \param localStruct This is a pointer to the local L0 trigger structure data. | |
696 | ||
ffc1a6f6 | 697 | assert(iloc < 16); |
69c14678 | 698 | assert(localStruct != NULL); |
699 | assert(fOutputTrigRecs != NULL); | |
a3d4b6ba | 700 | |
701 | // We must have at least one bit in each of the 4 strip words otherwise | |
702 | // if one of the words is zero it means we only have X or Y coordinate | |
703 | // information for a station or no coordinate on one of the stations at all. | |
704 | if (localStruct->fX2X1 == 0 or localStruct->fX4X3 == 0 or | |
705 | localStruct->fY2Y1 == 0 or localStruct->fY4Y3 == 0 | |
69c14678 | 706 | ) |
707 | { | |
708 | return; | |
709 | } | |
b39b98c8 | 710 | |
a3d4b6ba | 711 | // First try to identify the X and Y strips on MT1 that fired the trigger. |
712 | // Note: X strips are for the Y axis in ALICE coordinate system, | |
713 | // i.e. bending plane. and Y strips for the X axis. | |
714 | AliHLTInt32_t xPos, yPos; | |
715 | if (not FindStripsOnMT1(localStruct, xPos, yPos)) return; | |
716 | ||
69c14678 | 717 | // Check that we will not overflow the output buffer. |
718 | if (fOutputTrigRecsCount >= fMaxOutputTrigRecs) | |
719 | { | |
720 | HLTError("Output buffer has overflowed maximum element count of %d.", | |
721 | fMaxOutputTrigRecs | |
722 | ); | |
723 | fOverflowed = true; | |
724 | return; | |
725 | } | |
b39b98c8 | 726 | |
a3d4b6ba | 727 | AliHLTMUONTriggerRecordStruct& trigger = fOutputTrigRecs[fOutputTrigRecsCount]; |
728 | ||
729 | // Now try find all the X and Y strips on all 4 trigger chambers. | |
730 | AliHLTInt32_t stripPosX[4]; | |
731 | FindXStrips(localStruct, xPos, stripPosX); | |
732 | AliHLTInt32_t stripPosY[4]; | |
733 | FindYStrips(localStruct, yPos, stripPosY); | |
406c5bc3 | 734 | |
69c14678 | 735 | // hitset indicates which hits on chambers 7 to 10 have been found and filled. |
736 | bool hitset[4] = {false, false, false, false}; | |
b39b98c8 | 737 | |
a3d4b6ba | 738 | // Reconstruct the hits from the found strips. Also, fill the hitset |
739 | // flags and make sure the hits for which no valid strips were found get | |
740 | // set to a nil value. | |
741 | AliHLTUInt32_t xStrips[4] = { | |
742 | GetLocalX1(localStruct), GetLocalX2(localStruct), | |
743 | GetLocalX3(localStruct), GetLocalX4(localStruct) | |
744 | }; | |
745 | AliHLTUInt32_t yStrips[4] = { | |
746 | GetLocalY1(localStruct), GetLocalY2(localStruct), | |
747 | GetLocalY3(localStruct), GetLocalY4(localStruct) | |
748 | }; | |
749 | int hitCount = 0; | |
750 | AliHLTUInt8_t locId = GetLocalId(localStruct); | |
69c14678 | 751 | for (int i = 0; i < 4; i++) |
752 | { | |
a3d4b6ba | 753 | if (stripPosX[i] != -1 and stripPosY[i] != -1) |
69c14678 | 754 | { |
a3d4b6ba | 755 | ReconstructHit( |
756 | xStrips[i], yStrips[i], | |
757 | stripPosX[i], stripPosY[i], | |
758 | fCurrentCrateId, locId, i, | |
759 | trigger.fHit[i] | |
760 | ); | |
761 | hitset[i] = true; | |
762 | hitCount++; | |
763 | } | |
764 | else | |
765 | { | |
766 | trigger.fHit[i] = AliHLTMUONConstants::NilRecHitStruct(); | |
767 | hitset[i] = false; | |
69c14678 | 768 | } |
769 | } | |
770 | ||
406c5bc3 | 771 | // Construct the ID from the running counter fTrigRecId and use the |
772 | // regional counter, local counter and DDL id for the bottom 8 bits. | |
a3d4b6ba | 773 | trigger.fId = (fTrigRecId << 8) | fDDLBit | ((fCurrentRegional & 0x7) << 4) | (iloc & 0xF); |
69c14678 | 774 | |
406c5bc3 | 775 | // Increment the trigger record ID and warp it around at 0x7FFFFF since |
776 | // the bottom 8 bits are filled with the regional + local counters and the | |
777 | // sign bit in fOutputTrigRecs[fOutputTrigRecsCount].fId must be positive. | |
778 | fTrigRecId = (fTrigRecId + 1) & 0x007FFFFF; | |
b39b98c8 | 779 | |
a3d4b6ba | 780 | // Set the ideal Z coordinate used in line fit for trigger record to |
781 | // the same as the Z coordinate for the hits that were found, otherwise | |
782 | // use nominal coordinates. | |
783 | AliHLTFloat32_t chamberZ11 = -1603.5f; | |
784 | if (hitset[0]) chamberZ11 = trigger.fHit[0].fZ; | |
785 | if (hitset[1]) chamberZ11 = trigger.fHit[1].fZ; | |
786 | AliHLTFloat32_t chamberZ13 = -1703.5f; | |
787 | if (hitset[2]) chamberZ13 = trigger.fHit[2].fZ; | |
788 | if (hitset[3]) chamberZ13 = trigger.fHit[3].fZ; | |
789 | AliHLTMUONCalculations::IdealZ1(chamberZ11); | |
790 | AliHLTMUONCalculations::IdealZ2(chamberZ13); | |
b39b98c8 | 791 | |
a3d4b6ba | 792 | if (hitCount >= 3 and |
793 | AliHLTMUONCalculations::FitLineToTriggerRecord(trigger, hitset) | |
794 | ) | |
b39b98c8 | 795 | { |
69c14678 | 796 | // Calculate the momentum and fill in the flags and momentum fields. |
797 | AliHLTMUONCalculations::ComputeMomentum( | |
a3d4b6ba | 798 | AliHLTMUONCalculations::IdealX1(), |
799 | AliHLTMUONCalculations::IdealY1(), | |
800 | AliHLTMUONCalculations::IdealY2(), | |
801 | AliHLTMUONCalculations::IdealZ1(), | |
802 | AliHLTMUONCalculations::IdealZ2() | |
69c14678 | 803 | ); |
a3d4b6ba | 804 | |
805 | trigger.fPx = AliHLTMUONCalculations::Px(); | |
806 | trigger.fPy = AliHLTMUONCalculations::Py(); | |
807 | trigger.fPz = AliHLTMUONCalculations::Pz(); | |
69c14678 | 808 | |
a3d4b6ba | 809 | trigger.fFlags = AliHLTMUONUtils::PackTriggerRecordFlags( |
69c14678 | 810 | AliHLTMUONCalculations::Sign(), |
811 | hitset | |
812 | ); | |
80590aa1 | 813 | |
69c14678 | 814 | fOutputTrigRecsCount++; |
815 | } | |
a3d4b6ba | 816 | else if ((hitset[0] or hitset[1] or hitset[2] or hitset[3]) |
817 | and not fSuppressPartialTriggers | |
818 | ) | |
69c14678 | 819 | { |
a3d4b6ba | 820 | trigger.fPx = trigger.fPy = trigger.fPz = 0; |
821 | ||
822 | trigger.fFlags = AliHLTMUONUtils::PackTriggerRecordFlags( | |
69c14678 | 823 | kSignUnknown, |
824 | hitset | |
825 | ); | |
80590aa1 | 826 | |
69c14678 | 827 | fOutputTrigRecsCount++; |
828 | } | |
829 | } | |
830 | ||
831 | ||
832 | void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnError( | |
833 | ErrorCode code, const void* location | |
834 | ) | |
835 | { | |
836 | /// Logs an error message if there was a decoding problem with the DDL payload. | |
960d54ad | 837 | |
69c14678 | 838 | long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader); |
a5d4696f | 839 | if (fWarnOnly) |
840 | { | |
841 | HLTWarning("There is a problem with decoding the raw data." | |
842 | " %s (Error code: %d, at byte %d). Trying to recover from corrupt data.", | |
843 | ErrorCodeToMessage(code), code, bytepos | |
844 | ); | |
845 | } | |
846 | else | |
847 | { | |
848 | HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)", | |
849 | ErrorCodeToMessage(code), code, bytepos | |
850 | ); | |
851 | } | |
6efe69e7 | 852 | } |
69c14678 | 853 |