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