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