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