]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructor.cxx
Improving documentation and macros.
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONTriggerReconstructor.cxx
CommitLineData
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 53AliHLTMUONTriggerReconstructor::AliHLTMUONTriggerReconstructor() :
69c14678 54 AliHLTLogging(),
55 fDecoder()
56{
57 /// Default constructor.
58}
59
60
61AliHLTMUONTriggerReconstructor::~AliHLTMUONTriggerReconstructor()
62{
63 /// Default destructor.
64}
65
66
67bool 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 118void 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 129AliHLTMUONTriggerReconstructor::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 164bool 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
327void 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
513void 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 581void 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
685void 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
832void 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