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