b29eac286ae9d08430263a92d437ccf63733d1dc
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONTriggerReconstructor.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Indranil Das <indra.das@saha.ac.in>                                  *
7  *   Artur Szostak <artursz@iafrica.com>                                  *
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     *
14  * about the suitability of this software for any purpose. It is          *
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 // $Id$
19
20 /**********************************************************************
21  Created on : 16/05/2007
22  Purpose    : This class reads the tracker DDL files and gives the output
23               as AliMUONTriggerRecordStruct structures.
24  Author     : Indranil Das, HEP Division, SINP
25  Email      : indra.das@saha.ac.in | indra.ehep@gmail.com
26
27  Artur Szostak <artursz@iafrica.com>:
28   Completely reimplemented the lookup table to a simplified format.
29 **********************************************************************/
30
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 ///
42
43 #include "AliHLTMUONTriggerReconstructor.h"
44 #include "AliHLTMUONTriggerRecordsBlockStruct.h"
45 #include "AliHLTMUONTrigRecsDebugBlockStruct.h"
46 #include "AliHLTMUONUtils.h"
47 #include "AliHLTMUONConstants.h"
48 #include "AliHLTMUONCalculations.h"
49 #include "AliMUONConstants.h"
50 #include "AliRawDataHeader.h"
51 #include <vector>
52 #include <cassert>
53
54
55 const AliMUONLocalInfoStruct AliHLTMUONTriggerReconstructor::AliDecoderHandler::fgkNullStruct =
56 {
57         0x0, 0x0, 0x0, 0x0, 0x0
58 };
59
60
61 AliHLTMUONTriggerReconstructor::AliHLTMUONTriggerReconstructor() :
62         AliHLTLogging(),
63         fDecoder()
64 {
65         /// Default constructor.
66         
67         fDecoder.MaxRegionals(8);
68         fDecoder.MaxLocals(16);
69 }
70
71
72 AliHLTMUONTriggerReconstructor::~AliHLTMUONTriggerReconstructor()
73 {
74         /// Default destructor.
75 }
76
77
78 bool AliHLTMUONTriggerReconstructor::Run(
79                 const AliHLTUInt8_t* rawData,
80                 AliHLTUInt32_t rawDataSize,
81                 bool scalarEvent,
82                 AliHLTMUONTriggerRecordStruct* trigRecord,
83                 AliHLTUInt32_t& nofTrigRec
84         )
85 {
86         /// Runs the trigger reconstruction algorithm on the raw data.
87         /// \param [in] rawData  Pointer to the raw data DDL payload.
88         /// \param [in] rawDataSize  Size of the raw data DDL payload in bytes.
89         /// \param [in] scalarEvent  Indicates if the raw data should contain
90         ///      scalar data also.
91         /// \param [out] trigRecord  Pointer to output buffer for reconstructed
92         ///      trigger records.
93         /// \param [in,out] nofTrigRec  Initialy should indicate the number of
94         ///      elements that can be stored in the trigRecord array. It will
95         ///      contain the number of elements filled after this method has returned.
96         /// \return true if raw data was decoded and false if there was a problem
97         ///     with the raw data or we overflowed the output buffer.
98         ///
99         /// \note OverflowedOutputBuffer() can be used to check if the output
100         /// buffer 'trigRecord' was overflowed during this method call.
101         
102         // Reset and initialise some variables in the decoder.
103         fDecoder.GetHandler().MaxOutputTrigRecs(nofTrigRec);
104         fDecoder.GetHandler().OutputTrigRecs(trigRecord);
105         
106         if (not fDecoder.Decode(rawData, rawDataSize, scalarEvent))
107         {
108                 if (TryRecover())
109                 {
110                         /// Fix as long as the DARC header problem is not fixed in hardware by trigger colleagues
111                         if (fDecoder.GetHandler().HadNonWrongEventTypeError() or
112                             (fDecoder.GetHandler().HadWrongEventTypeError() and not fDecoder.GetHandler().DontPrintWrongEventError())
113                            )
114                         {
115                                 HLTWarning("There was a problem with the raw data."
116                                         " Recovered as much data as possible."
117                                         " Will continue processing the next event."
118                                 );
119                         }
120                 }
121                 else
122                 {
123                         HLTError("Failed to decode the trigger DDL raw data.");
124                         return false;
125                 }
126         }
127         
128         // nofTrigRec now becomes the output of how many trigger records were found.
129         nofTrigRec = fDecoder.GetHandler().OutputTrigRecsCount();
130         
131         return not fDecoder.GetHandler().OverflowedOutputBuffer();
132 }
133
134
135 void AliHLTMUONTriggerReconstructor::TryRecover(bool value)
136 {
137         /// Sets the flag indicating if the decoder should enable the error
138         /// recovery logic.
139         
140         fDecoder.TryRecover(value);
141         fDecoder.ExitOnError(not value);
142         fDecoder.GetHandler().WarnOnly(value);
143 }
144
145
146 AliHLTMUONTriggerReconstructor::AliDecoderHandler::AliDecoderHandler() :
147         AliMUONTriggerDDLDecoderEventHandler(),
148         AliHLTLogging(),
149         fLookupTable(),
150         fBufferStart(NULL),
151         fMaxOutputTrigRecs(0),
152         fOutputTrigRecsCount(0),
153         fOutputTrigRecs(NULL),
154         fTrigRecId(0),
155         fDDLBit(0),
156         fSuppressPartialTriggers(false),
157         fOverflowed(false),
158         fWarnOnly(false),
159         fUseLocalId(true),
160         fUseCrateId(true),
161         fCurrentCrateId(0),
162         fCurrentRegional(0),
163         fNextLocalIndex(0),
164         fPrevStruct(&fgkNullStruct),
165         fCurrentStruct(&fgkNullStruct),
166         fNextStruct(&fgkNullStruct),
167         fStoreInfo(false),
168         fInfoBufferSize(0),
169         fInfoBufferCount(0),
170         fInfoBuffer(NULL),
171         fDontPrintWrongEventError(false),
172         fHadWrongEventTypeError(false),
173         fHadNonWrongEventTypeError(false)
174 {
175         /// Default constructor just resets the lookup table to zero and local
176         /// structure marker pointers to NULL.
177         
178         for (AliHLTInt32_t i = 0; i < 16; i++)
179         for (AliHLTInt32_t j = 0; j < 16; j++)
180         for (AliHLTInt32_t k = 0; k < 4; k++)
181         for (AliHLTInt32_t n = 0; n < 2; n++)
182         for (AliHLTInt32_t m = 0; m < 16; m++)
183         {
184                 fLookupTable.fRow[i][j][k][n][m].fIdFlags = 0x0;
185                 fLookupTable.fRow[i][j][k][n][m].fX = 0;
186                 fLookupTable.fRow[i][j][k][n][m].fY = 0;
187                 fLookupTable.fRow[i][j][k][n][m].fZ = 0;
188         }
189 }
190
191
192 AliHLTMUONTriggerReconstructor::AliDecoderHandler::~AliDecoderHandler()
193 {
194         // Default destructor deletes allocated array.
195         
196         if (fInfoBuffer != NULL) delete [] fInfoBuffer;
197 }
198
199
200 bool AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindStripsOnMT1(
201                 AliHLTInt32_t& xPos, AliHLTInt32_t& yPos
202         )
203 {
204         /// This method will find the X and Y strip positions on stations MT1 of the
205         /// trigger system which were fired for the current L0 local trigger decision.
206         /// \param [out] xPos  The X strip that was fired.
207         /// \param [out] yPos  The Y strip that was fired.
208         /// \return  true is returned if a strip was fired, otherwise a warning is
209         ///      generated and false is returned.
210         /// \note Values for xPos and yPos are in the range [0..15].
211
212         // Try to identify the strips on MT1 (chambers 11 or 12) that fired
213         // the trigger and set yPos and xPos to the correct values.
214         // For the Y strips the yPos value might or might not have to be divided
215         // by 2. This depends on the switches in the trigger electronics and how
216         // they were configured. To avoid having to try to track this info we
217         // just use a trial and error method.
218         yPos = GetLocalYPos(fCurrentStruct);
219         AliHLTUInt32_t yStrips1 = GetLocalY1(fCurrentStruct);
220         AliHLTUInt32_t yStrips2 = GetLocalY2(fCurrentStruct);
221         if (((yStrips1 >> yPos) & 0x1) != 0x1 and ((yStrips2 >> yPos) & 0x1) != 0x1)
222         {
223                 if (((yStrips1 >> (yPos / 2)) & 0x1) == 0x1 or ((yStrips2 >> (yPos / 2)) & 0x1) == 0x1)
224                 {
225                         yPos = yPos / 2;
226                 }
227                 else
228                 {
229                         for (AliHLTInt32_t i = 1; i < 16; ++i)
230                         {
231                                 if (yPos + i < 16 and (((yStrips1 >> (yPos + i)) & 0x1) == 0x1 or
232                                                        ((yStrips2 >> (yPos + i)) & 0x1) == 0x1)
233                                    )
234                                 {
235                                         yPos = yPos + i;
236                                         break;
237                                 }
238                                 else if (yPos / 2 + i < 16 and (((yStrips1 >> (yPos / 2 + i)) & 0x1) == 0x1 or
239                                                                 ((yStrips2 >> (yPos / 2 + i)) & 0x1) == 0x1)
240                                         )
241                                 {
242                                         yPos = yPos / 2 + i;
243                                         break;
244                                 }
245                                 else if (yPos - i >= 0 and (((yStrips1 >> (yPos - i)) & 0x1) == 0x1 or
246                                                             ((yStrips2 >> (yPos - i)) & 0x1) == 0x1)
247                                         )
248                                 {
249                                         yPos = yPos - i;
250                                         break;
251                                 }
252                                 else if (yPos / 2 - i >= 0 and (((yStrips1 >> (yPos / 2 - i)) & 0x1) == 0x1 or
253                                                                 ((yStrips2 >> (yPos / 2 - i)) & 0x1) == 0x1)
254                                         )
255                                 {
256                                         yPos = yPos / 2 - i;
257                                         break;
258                                 }
259                         }
260                         if (((yStrips1 >> yPos) & 0x1) != 0x1 and ((yStrips2 >> yPos) & 0x1) != 0x1)
261                         {
262                                 // No y strip found in MT1 so this local trigger circuit does not
263                                 // pass the 3/4 coincidence requirement, so ignore it and continue.
264                                 HLTWarning("Could not find fired Y strip for local trigger"
265                                         " structure (regional structure = %d, crate ID = %d, ID = %d),"
266                                         " which corresponds to triggered strip YPos = %d.",
267                                         fCurrentRegional, fCurrentCrateId, GetLocalId(fCurrentStruct),
268                                         GetLocalYPos(fCurrentStruct)
269                                 );
270                                 return false;
271                         }
272                 }
273         }
274         
275         // Now find the X strip on MT1 that fired the trigger.
276         xPos = GetLocalXPos(fCurrentStruct) / 2;
277         AliHLTUInt32_t xStrips1 = GetLocalX1(fCurrentStruct);
278         AliHLTUInt32_t xStrips2 = GetLocalX2(fCurrentStruct);
279         if (((xStrips1 >> xPos) & 0x1) != 0x1 and ((xStrips2 >> xPos) & 0x1) != 0x1)
280         {
281                 for (AliHLTInt32_t i = 1; i < 16; ++i)
282                 {
283                         if (xPos + i < 16 and (((xStrips1 >> (xPos + i)) & 0x1) == 0x1 or
284                                                ((xStrips2 >> (xPos + i)) & 0x1) == 0x1)
285                            )
286                         {
287                                 xPos = xPos + i;
288                                 break;
289                         }
290                         else if (xPos - i >= 0 and (((xStrips1 >> (xPos - i)) & 0x1) == 0x1 or
291                                                     ((xStrips2 >> (xPos - i)) & 0x1) == 0x1)
292                                 )
293                         {
294                                 xPos = xPos - i;
295                                 break;
296                         }
297                 }
298                 if (((xStrips1 >> xPos) & 0x1) != 0x1 and ((xStrips2 >> xPos) & 0x1) != 0x1)
299                 {
300                         // No x strip found in MT1 so this local trigger circuit does not
301                         // pass the 3/4 coincidence requirement, so ignore it and continue.
302                         HLTWarning("Could not find fired X strip for local trigger"
303                                 " structure (regional structure = %d, crate ID = %d, ID = %d),"
304                                 " which corresponds to triggered strip XPos = %d.",
305                                 fCurrentRegional, fCurrentCrateId, GetLocalId(fCurrentStruct),
306                                 GetLocalXPos(fCurrentStruct)
307                         );
308                         return false;
309                 }
310         }
311         
312         return true;
313 }
314
315
316 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::SelectXPatterns(
317                 AliHLTUInt64_t strips[4]
318         )
319 {
320         // Select the correct X strips to use.
321         
322         assert( fCurrentStruct != NULL );
323         
324         strips[0] = AliHLTUInt64_t(GetLocalX1(fPrevStruct)) |
325                 (AliHLTUInt64_t(GetLocalX1(fCurrentStruct)) << 16) |
326                 (AliHLTUInt64_t(GetLocalX1(fNextStruct)) << 32);
327         
328         strips[1] = AliHLTUInt64_t(GetLocalX2(fPrevStruct)) |
329                 (AliHLTUInt64_t(GetLocalX2(fCurrentStruct)) << 16) |
330                 (AliHLTUInt64_t(GetLocalX2(fNextStruct)) << 32);
331                 
332         strips[2] = AliHLTUInt64_t(GetLocalX3(fPrevStruct)) |
333                 (AliHLTUInt64_t(GetLocalX3(fCurrentStruct)) << 16) |
334                 (AliHLTUInt64_t(GetLocalX3(fNextStruct)) << 32);
335                 
336         strips[3] = AliHLTUInt64_t(GetLocalX4(fPrevStruct)) |
337                 (AliHLTUInt64_t(GetLocalX4(fCurrentStruct)) << 16) |
338                 (AliHLTUInt64_t(GetLocalX4(fNextStruct)) << 32);
339 }
340
341
342 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::SelectYPatterns(
343                 AliHLTInt32_t xpos[4], AliHLTUInt32_t strips[4], AliHLTUInt8_t locId[4]
344         )
345 {
346         // Select the correct Y strip patterns and local IDs based on the X strip positions found.
347         
348         AliHLTUInt8_t locIdnext = fUseLocalId ? GetLocalId(fNextStruct) : AliHLTUInt8_t(fNextLocalIndex);
349         if (locIdnext >= 16) locIdnext = 0;
350         AliHLTUInt8_t locIdcurr = fUseLocalId ? GetLocalId(fCurrentStruct) : AliHLTUInt8_t(fNextLocalIndex-1);
351         if (locIdcurr >= 16) locIdcurr = 0;
352         AliHLTUInt8_t locIdprev = fUseLocalId ? GetLocalId(fPrevStruct) : AliHLTUInt8_t(fNextLocalIndex-2);
353         if (locIdprev >= 16) locIdprev = 0;
354         
355         UShort_t patterns[4][3] = {
356                 {GetLocalY1(fPrevStruct), GetLocalY1(fCurrentStruct), GetLocalY1(fNextStruct)},
357                 {GetLocalY2(fPrevStruct), GetLocalY2(fCurrentStruct), GetLocalY2(fNextStruct)},
358                 {GetLocalY3(fPrevStruct), GetLocalY3(fCurrentStruct), GetLocalY3(fNextStruct)},
359                 {GetLocalY4(fPrevStruct), GetLocalY4(fCurrentStruct), GetLocalY4(fNextStruct)}
360         };
361         
362         for (int i = 0; i < 4; i++)
363         {
364                 // Check if the Y strips for the different local structures are the
365                 // same physical strip. If they are then performs a bit or between the
366                 // patterns. This is necessary because the signal sometimes does not
367                 // propagate in time (in particular for cosmic runs). This has to do with
368                 // the calibration of the timings in the trigger electronics. The solution
369                 // here is to perform the bitwise or to form the correct strip pattern.
370                 UShort_t mergedPattern[3] = {patterns[i][0], patterns[i][1], patterns[i][2]};
371                 const AliHLTMUONTriggerRecoLutRow& lutnext = fLookupTable.fRow[fCurrentCrateId][locIdnext][i][1][0];
372                 const AliHLTMUONTriggerRecoLutRow& lutcurr = fLookupTable.fRow[fCurrentCrateId][locIdcurr][i][1][0];
373                 const AliHLTMUONTriggerRecoLutRow& lutprev = fLookupTable.fRow[fCurrentCrateId][locIdprev][i][1][0];
374                 if (lutprev.fX == lutcurr.fX and lutprev.fY == lutcurr.fY and lutprev.fZ == lutcurr.fZ)
375                 {
376                         mergedPattern[0] |= patterns[i][1];
377                         mergedPattern[1] |= patterns[i][0];
378                 }
379                 if (lutnext.fX == lutcurr.fX and lutnext.fY == lutcurr.fY and lutnext.fZ == lutcurr.fZ)
380                 {
381                         mergedPattern[1] |= patterns[i][2];
382                         mergedPattern[2] |= patterns[i][1];
383                 }
384         
385                 if (xpos[i] >= 32)
386                 {
387                         strips[i] = mergedPattern[2];
388                         locId[i] = locIdnext;
389                 }
390                 else if (xpos[i] >= 16)
391                 {
392                         strips[i] = mergedPattern[1];
393                         locId[i] = locIdcurr;
394                 }
395                 else  if (xpos[i] >= 0)
396                 {
397                         strips[i] = mergedPattern[0];
398                         locId[i] = locIdprev;
399                 }
400                 else
401                 {
402                         // If the X strip could not be found then just look on the
403                         // current local board strips.
404                         strips[i] = mergedPattern[1];
405                         locId[i] = locIdcurr;
406                 }
407         }
408 }
409
410
411 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindXStrips(
412                 AliHLTInt32_t startPos, AliHLTUInt64_t strips[4], AliHLTInt32_t pos[4]
413         )
414 {
415         /// Finds the X strips that were fired in the local trigger structures.
416         /// \param [in] startPos  The first X strip location to start looking from.
417         /// \param [in] strips  The X strip patterns for chambers 11 to 14 to use.
418         /// \param [out] pos  Array of X strip positions on chambers 11 to 14. pos[0]
419         ///     is for chamber 11, pos[1] for chamber 12 and so on.
420         ///     The elements of the array will contain -1 if no valid strip position
421         ///     was found for that chamber.
422         /// \note Values for startPos and pos are in the range [0..47], where 0..15 is
423         ///     for strip positions in the fPrevStruct patterns, 16..31 for fCurrentStruct
424         ///     and 32..47 for fNextStruct.
425         
426         assert( startPos >= 0 );
427         assert( fCurrentStruct != NULL );
428         
429         if (GetLocalSXDev(fCurrentStruct)) // check the direction of the deviation.
430         {
431                 for (int i = 0; i < 2; ++i)
432                 {
433                         if (((strips[i] >> startPos) & 0x1) == 0x1)
434                         {
435                                 pos[i] = startPos;
436                                 continue;
437                         }
438                         for (AliHLTInt32_t j = 1; j < 16; ++j)
439                         {
440                                 // We first check the straighter tracklet option, i.e higher momentum.
441                                 if (startPos - j >= 0 and ((strips[i] >> (startPos - j)) & 0x1) == 0x1)
442                                 {
443                                         pos[i] = startPos - j;
444                                         break;
445                                 }
446                                 else if (startPos + j < 48 and ((strips[i] >> (startPos + j)) & 0x1) == 0x1)
447                                 {
448                                         pos[i] = startPos + j;
449                                         break;
450                                 }
451                         }
452                         if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
453                 }
454                 
455                 // Given the MT1 coordinate 'startPos' and the deviation information we can
456                 // identify the X strip on MT2 that corresponds to the L0 trigger.
457                 // We find fired strips on MT2 by looking for strips around the position
458                 // endPos = (posX + deviation) / 2, where posX = GetLocalXPos(fCurrentStruct);
459                 // deviation = GetLocalXDev(fCurrentStruct)
460                 AliHLTInt32_t endPos = (GetLocalXPos(fCurrentStruct) + GetLocalXDev(fCurrentStruct)) / 2;
461                 endPos += 16; // fCurrentStruct strips start at bit 16.
462                 
463                 for (int i = 2; i < 4; ++i)
464                 {
465                         if (((strips[i] >> endPos) & 0x1) == 0x1)
466                         {
467                                 pos[i] = endPos;
468                                 continue;
469                         }
470                         for (AliHLTInt32_t j = 1; j < 16; ++j)
471                         {
472                                 if (endPos - j >= 0 and ((strips[i] >> (endPos - j)) & 0x1) == 0x1)
473                                 {
474                                         pos[i] = endPos - j;
475                                         break;
476                                 }
477                                 else if (endPos + j < 48 and ((strips[i] >> (endPos + j)) & 0x1) == 0x1)
478                                 {
479                                         pos[i] = endPos + j;
480                                         break;
481                                 }
482                         }
483                         if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
484                 }
485         }
486         else
487         {
488                 // Similar logic to the positive deviation case above, but with the
489                 // arithmetic inversed.
490                 for (int i = 0; i < 2; ++i)
491                 {
492                         if (((strips[i] >> startPos) & 0x1) == 0x1)
493                         {
494                                 pos[i] = startPos;
495                                 continue;
496                         }
497                         for (AliHLTInt32_t j = 1; j < 16; ++j)
498                         {
499                                 // We first check the straighter tracklet option, i.e higher momentum.
500                                 if (startPos + j < 48 and ((strips[i] >> (startPos + j)) & 0x1) == 0x1)
501                                 {
502                                         pos[i] = startPos + j;
503                                         break;
504                                 }
505                                 else if (startPos - j >= 0 and ((strips[i] >> (startPos - j)) & 0x1) == 0x1)
506                                 {
507                                         pos[i] = startPos - j;
508                                         break;
509                                 }
510                         }
511                         if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
512                 }
513                 
514                 AliHLTInt32_t endPos = (GetLocalXPos(fCurrentStruct) - GetLocalXDev(fCurrentStruct)) / 2;
515                 endPos += 16; // fCurrentStruct strips start at bit 16.
516                 
517                 for (int i = 2; i < 4; ++i)
518                 {
519                         if (((strips[i] >> endPos) & 0x1) == 0x1)
520                         {
521                                 pos[i] = endPos;
522                                 continue;
523                         }
524                         for (AliHLTInt32_t j = 1; j < 16; ++j)
525                         {
526                                 if (endPos + j < 48 and ((strips[i] >> (endPos + j)) & 0x1) == 0x1)
527                                 {
528                                         pos[i] = endPos + j;
529                                         break;
530                                 }
531                                 else if (endPos - j >= 0 and ((strips[i] >> (endPos - j)) & 0x1) == 0x1)
532                                 {
533                                         pos[i] = endPos - j;
534                                         break;
535                                 }
536                         }
537                         if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
538                 }
539         }
540 }
541
542
543 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindYStrips(
544                 AliHLTInt32_t startPos, AliHLTUInt32_t strips[4], AliHLTInt32_t pos[4]
545         )
546 {
547         /// Finds the Y strips that were fired in the local trigger structures.
548         /// \param [in] startPos  The first Y strip location to start looking from.
549         /// \param [in] strips  Array of Y strip patterns to look in for chamber 11 to 14.
550         /// \param [out] pos  Array of Y strip positions on chambers 11 to 14. pos[0]
551         ///     is for chamber 11, pos[1] for chamber 12 and so on.
552         ///     The elements of the array will contain -1 if no valid strip position
553         ///     was found for that chamber.
554         /// \note Values for startPos and pos are in the range [0..15].
555         
556         assert( startPos >= 0 );
557         
558         // First we scan from the i'th = startPos strip upwards (i.e. i-1, i, i+1, i+2 etc..)
559         // to find the first fired strip. Then we similarly scan downwards
560         // (i.e. i+1, i, i-1, i-2 etc..) to find the first fired strip.
561         // Ideally we should have all of posUp[i] == posDown[i] == startPos, but this
562         // need not be the case due to multiple scattering or if dealing with cosmic tracks.
563         AliHLTUInt8_t posUpCount = 0, posDownCount = 0, posNearestCount = 0;
564         AliHLTInt32_t posUp[4] = {-1, -1, -1, -1};
565         AliHLTInt32_t posDown[4] = {-1, -1, -1, -1};
566         AliHLTInt32_t posNearest[4] = {-1, -1, -1, -1};
567         for (AliHLTInt32_t n = 0; n < 4; n++)
568         {
569                 for (AliHLTInt32_t i = (startPos >= 1 ? startPos-1 : 0); i <= 15; i++)
570                 {
571                         if (((strips[n] >> i) & 0x1) == 0x1)
572                         {
573                                 posUp[n] = i;
574                                 posUpCount++;
575                                 break;
576                         }
577                 }
578                 for (AliHLTInt32_t i = startPos+1; i >= 0; i--)
579                 {
580                         if (((strips[n] >> i) & 0x1) == 0x1)
581                         {
582                                 posDown[n] = i;
583                                 posDownCount++;
584                                 break;
585                         }
586                 }
587                 
588                 // 20 Nov 2009: Added scanning on either side of startPos to find the
589                 // nearest strip to startPos for pathological cases, where there is
590                 // a larger angle or scatter in Y strips than +/- 1 strip, eg. cosmics.
591                 if (((strips[n] >> startPos) & 0x1) == 0x1)
592                 {
593                         posNearest[n] = startPos;
594                         posNearestCount++;
595                 }
596                 else
597                 {
598                         for (AliHLTInt32_t i = 1; i < 16; ++i)
599                         {
600                                 if (((strips[n] >> (startPos + i)) & 0x1) == 0x1)
601                                 {
602                                         posNearest[n] = startPos + i;
603                                         posNearestCount++;
604                                         break;
605                                 }
606                                 else if (((strips[n] >> (startPos - i)) & 0x1) == 0x1)
607                                 {
608                                         posNearest[n] = startPos - i;
609                                         posNearestCount++;
610                                         break;
611                                 }
612                         }
613                 }
614         }
615         
616         // Now select either posUp or posDown, whichever has the most found strips.
617         if (posUpCount >= posDownCount and posUpCount >= posNearestCount)
618         {
619                 for (AliHLTInt32_t n = 0; n < 4; n++)
620                         pos[n] = posUp[n];
621         }
622         else if (posDownCount >= posUpCount and posDownCount >= posNearestCount)
623         {
624                 for (AliHLTInt32_t n = 0; n < 4; n++)
625                         pos[n] = posDown[n];
626         }
627         else
628         {
629                 for (AliHLTInt32_t n = 0; n < 4; n++)
630                         pos[n] = posNearest[n];
631         }
632 }
633
634
635 const AliHLTMUONTriggerRecoLutRow& AliHLTMUONTriggerReconstructor::AliDecoderHandler::GetLutRowX(
636                 AliHLTInt32_t xPos, AliHLTUInt8_t chamber
637         )
638 {
639         // Fetches the appropriate LUT row for a given strip X and Y position.
640         
641         assert( chamber <= 3 );
642         assert( fCurrentCrateId < 16 );
643         
644         int locId = 0;
645         int pos = 0;
646         if (xPos >= 32)
647         {
648                 locId = fUseLocalId ? GetLocalId(fNextStruct) : fNextLocalIndex;
649                 pos = xPos - 32;
650         }
651         else if (xPos >= 16)
652         {
653                 locId = fUseLocalId ? GetLocalId(fCurrentStruct) : fNextLocalIndex-1;
654                 pos = xPos - 16;
655         }
656         else if (xPos >= 0)
657         {
658                 locId = fUseLocalId ? GetLocalId(fPrevStruct) : fNextLocalIndex-2;
659                 pos = xPos;
660         }
661         if (locId < 0 or locId >= 16) locId = 0;
662         if (pos < 0 or pos >= 16) pos = 0;
663         
664         return fLookupTable.fRow[fCurrentCrateId][locId][chamber][0][pos];
665 }
666
667
668 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
669                 AliHLTUInt64_t xStrips, AliHLTUInt32_t yStrips,
670                 AliHLTInt32_t xPos, AliHLTInt32_t yPos, AliHLTUInt8_t yLocId,
671                 AliHLTUInt8_t chamber, AliHLTMUONRecHitStruct& hit
672         )
673 {
674         /// Reconstructs the hit coordinates for the given chamber from the
675         /// strip and fired strip information provided.
676         /// \param [in] xStrips  The X strip pattern for the given chamber.
677         /// \param [in] yStrips  The Y strip pattern for the given chamber.
678         /// \param [in] xPos  The position of the X strip that was fired.
679         /// \param [in] yPos  The position of the Y strip that was fired.
680         /// \param [in] chamber  The chamber on which the strips were found.
681         ///      Valid range [0..3].
682         /// \param [out] hit  This will be filled with the reconstructed hit.
683
684         assert( 0 <= xPos and xPos < 48 );
685         assert( 0 <= yPos and yPos < 16 );
686         assert( ((xStrips >> xPos) & 0x1) == 0x1 );
687         assert( ((yStrips >> yPos) & 0x1) == 0x1 );
688         assert( chamber <= 3 );
689         assert( fCurrentCrateId < 16 );
690         assert( yLocId < 16 );
691         
692         const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(xPos, chamber);
693         
694         // Decode the Y position of the hit from the strip position information.
695         // If two neighbouring strips were fired then we decluster the strips like
696         // the L0 electronics does by taking the middle position of the two strips.
697         if (xPos > 0 and ((xStrips >> (xPos-1)) & 0x1) == 0x1)
698         {
699                 if (((xStrips >> (xPos+1)) & 0x1) == 0x1)
700                 {
701                         // Strips fired on both sides of strip at xPos so just use the middle one.
702                         hit.fFlags = lut.fIdFlags;
703                         hit.fY = lut.fY;
704                         hit.fZ = lut.fZ;
705                 }
706                 else
707                 {
708                         // Second strip fired below the one at xPos, so decluster.
709                         assert(xPos-1 < 48);
710                         const AliHLTMUONTriggerRecoLutRow& lut2 = GetLutRowX(xPos-1, chamber);
711                         hit.fFlags = lut.fIdFlags;
712                         hit.fY = (lut2.fY + lut.fY) * 0.5;
713                         hit.fZ = (lut2.fZ + lut.fZ) * 0.5;
714                 }
715         }
716         else
717         {
718                 if (((xStrips >> (xPos+1)) & 0x1) == 0x1)
719                 {
720                         // Second strip fired above the one at xPos, so decluster.
721                         assert(xPos+1 < 48);
722                         const AliHLTMUONTriggerRecoLutRow& lut2 = GetLutRowX(xPos+1, chamber);
723                         hit.fFlags = lut.fIdFlags;
724                         hit.fY = (lut2.fY + lut.fY) * 0.5;
725                         hit.fZ = (lut2.fZ + lut.fZ) * 0.5;
726                 }
727                 else
728                 {
729                         // Only strip at xPos fired and neither of its two neighbours.
730                         hit.fFlags = lut.fIdFlags;
731                         hit.fY = lut.fY;
732                         hit.fZ = lut.fZ;
733                 }
734         }
735         
736         // Similarly decode the X position of the hit from the strip position information.
737         // Also decluster like for the Y strips.
738         if (yPos > 0 and ((yStrips >> (yPos-1)) & 0x1) == 0x1)
739         {
740                 if (((yStrips >> (yPos+1)) & 0x1) == 0x1)
741                 {
742                         // Strips fired on both sides of strip at yPos so just use the middle one.
743                         hit.fX = fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX;
744                 }
745                 else
746                 {
747                         // Second strip fired below the one at yPos, so decluster.
748                         assert(yPos-1 < 16);
749                         hit.fX = (fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos-1].fX
750                                 + fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX) * 0.5;
751                 }
752         }
753         else
754         {
755                 if (((yStrips >> (yPos+1)) & 0x1) == 0x1)
756                 {
757                         // Second strip fired above the one at yPos, so decluster.
758                         assert(yPos+1 < 16);
759                         hit.fX = (fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos+1].fX
760                                 + fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX) * 0.5;
761                 }
762                 else
763                 {
764                         // Only strip at yPos fired and neither of its two neighbours.
765                         hit.fX = fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX;
766                 }
767         }
768 }
769
770
771 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnNewRegionalStructV2(
772                 UInt_t num,
773                 const AliMUONRegionalHeaderStruct* regionalStruct,
774                 const AliMUONRegionalScalarsStruct* /*scalars*/,
775                 const void* /*data*/
776         )
777 {
778         // Reset the local trigger structure pointers, and mark the current regional
779         // structure number and Crate ID.
780         
781         fCurrentRegional = num;
782         fCurrentCrateId = (fUseCrateId ? GetRegionalId(regionalStruct) : num);
783         fPrevStruct = fCurrentStruct = fNextStruct = &fgkNullStruct;
784 }
785
786
787 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnEndOfRegionalStructV2(
788                 UInt_t /*num*/,
789                 const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
790                 const AliMUONRegionalScalarsStruct* /*scalars*/,
791                 const void* /*data*/
792         )
793 {
794         // Process the last local trigger structure.
795         
796         fPrevStruct = fCurrentStruct;
797         fCurrentStruct = fNextStruct;
798         fNextStruct = &fgkNullStruct;
799         
800         // The index numbers for fPrevStruct and fCurrentStruct are calculated from
801         // fNextLocalIndex in ProcessLocalStruct so we need to increment it correctly.
802         ++fNextLocalIndex;
803         
804         ProcessLocalStruct();
805 }
806
807
808 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
809                 UInt_t iloc,
810                 const AliMUONLocalInfoStruct* localStruct,
811                 const AliMUONLocalScalarsStruct* /*scalars*/
812         )
813 {
814         // Update pointers and process the current local trigger structure.
815         
816         assert(iloc < 16);
817         assert(localStruct != NULL);
818         
819         fPrevStruct = fCurrentStruct;
820         fCurrentStruct = fNextStruct;
821         fNextStruct = localStruct;
822         fNextLocalIndex = iloc;
823         ProcessLocalStruct();
824 }
825
826
827 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ProcessLocalStruct()
828 {
829         /// Converts the fCurrentStruct local trigger structure from the L0 into a trigger record.
830         /// The dHLT trigger records is then used as a seed for tracking algorithms.
831         /// \note fOutputTrigRecs must be set before calling the decoder to decode
832         ///    a new raw data buffer.
833
834         assert(fOutputTrigRecs != NULL);
835         
836         // If the current local trigger structure does not have a decision then skip it.
837         if (GetLocalDec(fCurrentStruct) == 0) return;
838         
839         // First try to identify the X and Y strips on MT1 that fired the trigger.
840         // Note: X strips are for the Y axis in ALICE coordinate system,
841         // i.e. bending plane. and Y strips for the X axis.
842         AliHLTInt32_t xPos, yPos;
843         if (not FindStripsOnMT1(xPos, yPos)) return;
844         
845         // Check that we will not overflow the output buffer.
846         if (fOutputTrigRecsCount >= fMaxOutputTrigRecs)
847         {
848                 HLTError("Output buffer has overflowed maximum element count of %d.",
849                         fMaxOutputTrigRecs
850                 );
851                 fOverflowed = true;
852                 return;
853         }
854         
855         AliHLTMUONTriggerRecordStruct& trigger = fOutputTrigRecs[fOutputTrigRecsCount];
856         
857         // Now try find all the fired X and Y strips on all 4 trigger chambers.
858         
859         AliHLTUInt64_t xStrips[4];
860         SelectXPatterns(xStrips);
861         AliHLTInt32_t stripPosX[4];
862         // Note: the +16 is because FindStripsOnMT1 returns value in the range [0..15]
863         // for fCurrentStruct, but we need the value in the range [0..47].
864         FindXStrips(xPos+16, xStrips, stripPosX);
865         AliHLTUInt32_t yStrips[4]; AliHLTUInt8_t locId[4];
866         SelectYPatterns(stripPosX, yStrips, locId);
867         AliHLTInt32_t stripPosY[4];
868         FindYStrips(yPos, yStrips, stripPosY);
869         
870         // hitset indicates which hits on chambers 7 to 10 have been found and filled.
871         bool hitset[4] = {false, false, false, false};
872         
873         // Reconstruct the hits from the found strips. Also, fill the hitset
874         // flags and make sure the hits for which no valid strips were found get
875         // set to a nil value.
876         int hitCount = 0;
877         for (int i = 0; i < 4; i++)
878         {
879                 if (stripPosX[i] != -1 and stripPosY[i] != -1)
880                 {
881                         ReconstructHit(
882                                         xStrips[i], yStrips[i],
883                                         stripPosX[i], stripPosY[i],
884                                         locId[i], i, trigger.fHit[i]
885                                 );
886                         hitset[i] = true;
887                         hitCount++;
888                 }
889                 else
890                 {
891                         trigger.fHit[i] = AliHLTMUONConstants::NilRecHitStruct();
892                         hitset[i] = false;
893                 }
894         }
895         
896         if (hitCount < 3)
897         {
898                 // If we could not find at least 3 hits, but the trigger fired, then
899                 // maybe we have a pathalogical case where 3 X strips and 3 Y strips
900                 // fired but one chamber has an X, one a Y and only the other 2 have both
901                 // X and Y strips fired.
902                 // In such a case we need to try fit a line to X and Y independantly
903                 // and form the hits from the best line fit.
904                 
905                 AliHLTFloat32_t x[4], zx[4], y[4], zy[4];
906                 AliHLTUInt32_t nx = 0, ny = 0;
907                 for (int i = 0; i < 4; i++)
908                 {
909                         if (stripPosX[i] != -1)
910                         {
911                                 const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(stripPosX[i], i);
912                                 y[ny] = lut.fY;
913                                 zy[ny] = lut.fZ;
914                                 ++ny;
915                         }
916                         if (stripPosY[i] != -1)
917                         {
918                                 const AliHLTMUONTriggerRecoLutRow& lut =
919                                         fLookupTable.fRow[fCurrentCrateId][locId[i]][i][1][stripPosY[i]];
920                                 x[nx] = lut.fX;
921                                 zx[nx] = lut.fZ;
922                                 ++nx;
923                         }
924                 }
925                 
926                 AliHLTFloat32_t mx = 0, cx = 0, my = 0, cy = 0;
927                 bool xfitted = AliHLTMUONCalculations::FitLineToData(x, zx, nx);
928                 mx = AliHLTMUONCalculations::Mzx();
929                 cx = AliHLTMUONCalculations::Czx();
930                 bool yfitted = AliHLTMUONCalculations::FitLineToData(y, zy, ny);
931                 my = AliHLTMUONCalculations::Mzx();
932                 cy = AliHLTMUONCalculations::Czx();
933                 if (xfitted and yfitted)
934                 {
935                         for (int i = 0; i < 4; i++)
936                         {
937                                 if (hitset[i]) continue;  // Leave the found hits alone.
938                                 if (stripPosX[i] != -1)
939                                 {
940                                         // Got X strip but no hit, so Y strip is missing.
941                                         // Thus we have a good Y coordinate but poor X.
942                                         const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(stripPosX[i], i);
943                                         trigger.fHit[i].fFlags = lut.fIdFlags;
944                                         trigger.fHit[i].fX = mx * lut.fZ + cx;
945                                         trigger.fHit[i].fY = lut.fY;
946                                         trigger.fHit[i].fZ = lut.fZ;
947                                         hitset[i] = true;
948                                         hitCount++;
949                                 }
950                                 else if (stripPosY[i] != -1)
951                                 {
952                                         // Got Y strip but no hit, so X strip is missing.
953                                         // Thus we have a good X coordinate but poor Y.
954                                         const AliHLTMUONTriggerRecoLutRow& lut =
955                                                 fLookupTable.fRow[fCurrentCrateId][locId[i]][i][1][stripPosY[i]];
956                                         trigger.fHit[i].fFlags = lut.fIdFlags;
957                                         trigger.fHit[i].fX = lut.fX;
958                                         trigger.fHit[i].fY = my * lut.fZ + cy;
959                                         trigger.fHit[i].fZ = lut.fZ;
960                                         hitset[i] = true;
961                                         hitCount++;
962                                 }
963                         }
964                 }
965         }
966         
967         // If 4 hits found then check if they are all good, otherwise find the 3
968         // best fitting ones.
969         if (hitCount > 3)
970         {
971                 AliHLTFloat32_t dx = AliMUONConstants::TriggerNonBendingReso();
972                 AliHLTFloat32_t dy = AliMUONConstants::TriggerBendingReso();
973                 AliHLTMUONCalculations::SigmaX2(dx*dx);
974                 AliHLTMUONCalculations::SigmaY2(dy*dy);
975                 
976                 AliHLTFloat32_t chi2 = AliHLTMUONCalculations::ComputeChi2(trigger, hitset);
977                 if (chi2 != -1 and chi2 > 5.*4)  // check 5 sigma cut.
978                 {
979                         // Poor fit so look for best 3 points.
980                         int worstHit = -1;
981                         AliHLTFloat32_t bestchi2 = 1e38;
982                         for (int j = 0; j < 4; j++)
983                         {
984                                 bool tmphitset[4] = {true, true, true, true};
985                                 tmphitset[j] = false;
986                                 AliHLTFloat32_t tmpchi2 = AliHLTMUONCalculations::ComputeChi2(trigger, tmphitset);
987                                 if (tmpchi2 * 4 < chi2 * 3 and tmpchi2 < bestchi2)
988                                 {
989                                         bestchi2 = tmpchi2;
990                                         worstHit = j;
991                                 }
992                         }
993                         if (worstHit != -1)
994                         {
995                                 for (int j = 0; j < 4; j++) hitset[j] = true;
996                                 hitset[worstHit] = false;
997                                 trigger.fHit[worstHit] = AliHLTMUONConstants::NilRecHitStruct();
998                         }
999                 }
1000         }
1001
1002         // Construct the ID from the running counter fTrigRecId and use the
1003         // regional counter, local counter and DDL id for the bottom 8 bits.
1004         AliHLTUInt8_t iloc = fNextLocalIndex-1;
1005         trigger.fId = (fTrigRecId << 8) | fDDLBit | ((fCurrentRegional & 0x7) << 4) | (iloc & 0xF);
1006
1007         // Increment the trigger record ID and warp it around at 0x7FFFFF since
1008         // the bottom 8 bits are filled with the regional + local counters and the
1009         // sign bit in fOutputTrigRecs[fOutputTrigRecsCount].fId must be positive.
1010         fTrigRecId = (fTrigRecId + 1) & 0x007FFFFF;
1011         
1012         // Set the ideal Z coordinate used in line fit for trigger record to
1013         // the same as the Z coordinate for the hits that were found, otherwise
1014         // use nominal coordinates.
1015         AliHLTFloat32_t chamberZ11 = -1603.5f;
1016         if (hitset[0]) chamberZ11 = trigger.fHit[0].fZ;
1017         if (hitset[1]) chamberZ11 = trigger.fHit[1].fZ;
1018         AliHLTFloat32_t chamberZ13 = -1703.5f;
1019         if (hitset[2]) chamberZ13 = trigger.fHit[2].fZ;
1020         if (hitset[3]) chamberZ13 = trigger.fHit[3].fZ;
1021         AliHLTMUONCalculations::IdealZ1(chamberZ11);
1022         AliHLTMUONCalculations::IdealZ2(chamberZ13);
1023         
1024         bool trigAdded = false;
1025         
1026         if (hitCount >= 3 and
1027             AliHLTMUONCalculations::FitLineToTriggerRecord(trigger, hitset)
1028            )
1029         {
1030                 // Calculate the momentum and fill in the flags and momentum fields.
1031                 AliHLTMUONCalculations::ComputeMomentum(
1032                                 AliHLTMUONCalculations::IdealX1(),
1033                                 AliHLTMUONCalculations::IdealY1(),
1034                                 AliHLTMUONCalculations::IdealY2(),
1035                                 AliHLTMUONCalculations::IdealZ1(),
1036                                 AliHLTMUONCalculations::IdealZ2()
1037                         );
1038                 
1039                 trigger.fPx = AliHLTMUONCalculations::Px();
1040                 trigger.fPy = AliHLTMUONCalculations::Py();
1041                 trigger.fPz = AliHLTMUONCalculations::Pz();
1042
1043                 trigger.fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
1044                                 AliHLTMUONCalculations::Sign(),
1045                                 hitset
1046                         );
1047                 
1048                 fOutputTrigRecsCount++;
1049                 trigAdded = true;
1050         }
1051         else if ((hitset[0] or hitset[1] or hitset[2] or hitset[3])
1052                  and not fSuppressPartialTriggers
1053                 )
1054         {
1055                 trigger.fPx = trigger.fPy = trigger.fPz = 0;
1056                 
1057                 trigger.fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
1058                                 kSignUnknown,
1059                                 hitset
1060                         );
1061                 
1062                 fOutputTrigRecsCount++;
1063                 trigAdded = true;
1064         }
1065         
1066         if (trigAdded and fStoreInfo)
1067         {
1068                 // Allocate or reallocate buffer.
1069                 if (fInfoBuffer == NULL)
1070                 {
1071                         try
1072                         {
1073                                 fInfoBuffer = new AliHLTMUONTrigRecInfoStruct[256];
1074                         }
1075                         catch (...)
1076                         {
1077                                 HLTError("Could not allocate buffer space for debug information.");
1078                                 return;
1079                         }
1080                         fInfoBufferSize = 256;
1081                 }
1082                 else if (fInfoBufferCount >= fInfoBufferSize)
1083                 {
1084                         AliHLTMUONTrigRecInfoStruct* newbuf = NULL;
1085                         try
1086                         {
1087                                 newbuf = new AliHLTMUONTrigRecInfoStruct[fInfoBufferSize*2];
1088                         }
1089                         catch (...)
1090                         {
1091                                 HLTError("Could not allocate more buffer space for debug information.");
1092                                 return;
1093                         }
1094                         for (AliHLTUInt32_t i = 0; i < fInfoBufferSize; ++i) newbuf[i] = fInfoBuffer[i];
1095                         delete [] fInfoBuffer;
1096                         fInfoBuffer = newbuf;
1097                         fInfoBufferSize = fInfoBufferSize*2;
1098                 }
1099                 
1100                 fInfoBuffer[fInfoBufferCount].fTrigRecId = trigger.fId;
1101                 for (int i = 0; i < 4; ++i)
1102                 {
1103                         if (trigger.fHit[i] != AliHLTMUONConstants::NilRecHitStruct())
1104                         {
1105                                 fInfoBuffer[fInfoBufferCount].fDetElemId[i] =
1106                                         AliHLTMUONUtils::GetDetElemIdFromFlags(trigger.fHit[i].fFlags);
1107                         }
1108                         else
1109                         {
1110                                 fInfoBuffer[fInfoBufferCount].fDetElemId[i] = -1;
1111                         }
1112                 }
1113                 fInfoBuffer[fInfoBufferCount].fZmiddle = AliHLTMUONCalculations::Zf();
1114                 fInfoBuffer[fInfoBufferCount].fBl = AliHLTMUONCalculations::QBL();
1115                 fInfoBuffer[fInfoBufferCount].fL0Struct = *fCurrentStruct;
1116                 fInfoBuffer[fInfoBufferCount].fL0StructPrev = *fPrevStruct;
1117                 fInfoBuffer[fInfoBufferCount].fL0StructNext = *fNextStruct;
1118                 ++fInfoBufferCount;
1119         }
1120 }
1121
1122
1123 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnError(
1124                 ErrorCode code, const void* location
1125         )
1126 {
1127         /// Logs an error message if there was a decoding problem with the DDL payload.
1128         
1129         long bytepos = long(location) - long(fBufferStart) + sizeof(AliRawDataHeader);
1130         if (code == kWrongEventType)
1131         {
1132                 fHadWrongEventTypeError = true;
1133                 
1134                 /// Do not generate an error message if the fDontPrintWrongEventError option is set.
1135                 if (fDontPrintWrongEventError) return;
1136         }
1137         else
1138         {
1139                 fHadNonWrongEventTypeError = true;
1140         }
1141         if (fWarnOnly)
1142         {
1143                 HLTWarning("There is a problem with decoding the raw data."
1144                         " %s (Error code: %d, at byte %d). Trying to recover from corrupt data.",
1145                         ErrorCodeToMessage(code), code, bytepos
1146                 );
1147         }
1148         else
1149         {
1150                 HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
1151                         ErrorCodeToMessage(code), code, bytepos
1152                 );
1153         }
1154 }
1155