1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Indranil Das <indra.das@saha.ac.in> *
7 * Artur Szostak <artursz@iafrica.com> *
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 **************************************************************************/
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
27 Artur Szostak <artursz@iafrica.com>:
28 Completely reimplemented the lookup table to a simplified format.
29 **********************************************************************/
32 /// @file AliHLTMUONTriggerReconstructor.cxx
33 /// @author Indranil Das <indra.das@saha.ac.in>,
34 /// Artur Szostak <artursz@iafrica.com>
36 /// @brief Implementation of the AliHLTMUONTriggerReconstructor class.
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.
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"
54 const AliMUONLocalInfoStruct AliHLTMUONTriggerReconstructor::AliDecoderHandler::fgkNullStruct =
56 0x0, 0x0, 0x0, 0x0, 0x0
60 AliHLTMUONTriggerReconstructor::AliHLTMUONTriggerReconstructor() :
64 /// Default constructor.
66 fDecoder.MaxRegionals(8);
67 fDecoder.MaxLocals(16);
71 AliHLTMUONTriggerReconstructor::~AliHLTMUONTriggerReconstructor()
73 /// Default destructor.
77 bool AliHLTMUONTriggerReconstructor::Run(
78 const AliHLTUInt8_t* rawData,
79 AliHLTUInt32_t rawDataSize,
81 AliHLTMUONTriggerRecordStruct* trigRecord,
82 AliHLTUInt32_t& nofTrigRec
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
90 /// \param [out] trigRecord Pointer to output buffer for reconstructed
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.
98 /// \note OverflowedOutputBuffer() can be used to check if the output
99 /// buffer 'trigRecord' was overflowed during this method call.
101 // Reset and initialise some variables in the decoder.
102 fDecoder.GetHandler().MaxOutputTrigRecs(nofTrigRec);
103 fDecoder.GetHandler().OutputTrigRecs(trigRecord);
105 if (not fDecoder.Decode(rawData, rawDataSize, scalarEvent))
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())
114 HLTWarning("There was a problem with the raw data."
115 " Recovered as much data as possible."
116 " Will continue processing the next event."
122 HLTError("Failed to decode the trigger DDL raw data.");
127 // nofTrigRec now becomes the output of how many trigger records were found.
128 nofTrigRec = fDecoder.GetHandler().OutputTrigRecsCount();
130 return not fDecoder.GetHandler().OverflowedOutputBuffer();
134 void AliHLTMUONTriggerReconstructor::TryRecover(bool value)
136 /// Sets the flag indicating if the decoder should enable the error
139 fDecoder.TryRecover(value);
140 fDecoder.ExitOnError(not value);
141 fDecoder.GetHandler().WarnOnly(value);
145 AliHLTMUONTriggerReconstructor::AliDecoderHandler::AliDecoderHandler() :
146 AliMUONTriggerDDLDecoderEventHandler(),
150 fMaxOutputTrigRecs(0),
151 fOutputTrigRecsCount(0),
152 fOutputTrigRecs(NULL),
155 fSuppressPartialTriggers(false),
163 fPrevStruct(&fgkNullStruct),
164 fCurrentStruct(&fgkNullStruct),
165 fNextStruct(&fgkNullStruct),
170 fDontPrintWrongEventError(false),
171 fHadWrongEventTypeError(false),
172 fHadNonWrongEventTypeError(false)
174 /// Default constructor just resets the lookup table to zero and local
175 /// structure marker pointers to NULL.
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++)
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;
191 AliHLTMUONTriggerReconstructor::AliDecoderHandler::~AliDecoderHandler()
193 // Default destructor deletes allocated array.
195 if (fInfoBuffer != NULL) delete [] fInfoBuffer;
199 bool AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindStripsOnMT1(
200 AliHLTInt32_t& xPos, AliHLTInt32_t& yPos
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].
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)
222 if (((yStrips1 >> (yPos / 2)) & 0x1) == 0x1 or ((yStrips2 >> (yPos / 2)) & 0x1) == 0x1)
228 for (AliHLTInt32_t i = 1; i < 16; ++i)
230 if (yPos + i < 16 and (((yStrips1 >> (yPos + i)) & 0x1) == 0x1 or
231 ((yStrips2 >> (yPos + i)) & 0x1) == 0x1)
237 else if (yPos / 2 + i < 16 and (((yStrips1 >> (yPos / 2 + i)) & 0x1) == 0x1 or
238 ((yStrips2 >> (yPos / 2 + i)) & 0x1) == 0x1)
244 else if (yPos - i >= 0 and (((yStrips1 >> (yPos - i)) & 0x1) == 0x1 or
245 ((yStrips2 >> (yPos - i)) & 0x1) == 0x1)
251 else if (yPos / 2 - i >= 0 and (((yStrips1 >> (yPos / 2 - i)) & 0x1) == 0x1 or
252 ((yStrips2 >> (yPos / 2 - i)) & 0x1) == 0x1)
259 if (((yStrips1 >> yPos) & 0x1) != 0x1 and ((yStrips2 >> yPos) & 0x1) != 0x1)
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)
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)
280 for (AliHLTInt32_t i = 1; i < 16; ++i)
282 if (xPos + i < 16 and (((xStrips1 >> (xPos + i)) & 0x1) == 0x1 or
283 ((xStrips2 >> (xPos + i)) & 0x1) == 0x1)
289 else if (xPos - i >= 0 and (((xStrips1 >> (xPos - i)) & 0x1) == 0x1 or
290 ((xStrips2 >> (xPos - i)) & 0x1) == 0x1)
297 if (((xStrips1 >> xPos) & 0x1) != 0x1 and ((xStrips2 >> xPos) & 0x1) != 0x1)
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)
315 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::SelectXPatterns(
316 AliHLTUInt64_t strips[4]
319 // Select the correct X strips to use.
321 assert( fCurrentStruct != NULL );
323 strips[0] = AliHLTUInt64_t(GetLocalX1(fPrevStruct)) |
324 (AliHLTUInt64_t(GetLocalX1(fCurrentStruct)) << 16) |
325 (AliHLTUInt64_t(GetLocalX1(fNextStruct)) << 32);
327 strips[1] = AliHLTUInt64_t(GetLocalX2(fPrevStruct)) |
328 (AliHLTUInt64_t(GetLocalX2(fCurrentStruct)) << 16) |
329 (AliHLTUInt64_t(GetLocalX2(fNextStruct)) << 32);
331 strips[2] = AliHLTUInt64_t(GetLocalX3(fPrevStruct)) |
332 (AliHLTUInt64_t(GetLocalX3(fCurrentStruct)) << 16) |
333 (AliHLTUInt64_t(GetLocalX3(fNextStruct)) << 32);
335 strips[3] = AliHLTUInt64_t(GetLocalX4(fPrevStruct)) |
336 (AliHLTUInt64_t(GetLocalX4(fCurrentStruct)) << 16) |
337 (AliHLTUInt64_t(GetLocalX4(fNextStruct)) << 32);
341 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::SelectYPatterns(
342 AliHLTInt32_t xpos[4], AliHLTUInt32_t strips[4], AliHLTUInt8_t locId[4]
345 // Select the correct Y strip patterns and local IDs based on the X strip positions found.
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;
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)}
361 for (int i = 0; i < 4; i++)
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)
375 mergedPattern[0] |= patterns[i][1];
376 mergedPattern[1] |= patterns[i][0];
378 if (lutnext.fX == lutcurr.fX and lutnext.fY == lutcurr.fY and lutnext.fZ == lutcurr.fZ)
380 mergedPattern[1] |= patterns[i][2];
381 mergedPattern[2] |= patterns[i][1];
386 strips[i] = mergedPattern[2];
387 locId[i] = locIdnext;
389 else if (xpos[i] >= 16)
391 strips[i] = mergedPattern[1];
392 locId[i] = locIdcurr;
394 else if (xpos[i] >= 0)
396 strips[i] = mergedPattern[0];
397 locId[i] = locIdprev;
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;
410 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindXStrips(
411 AliHLTInt32_t startPos, AliHLTUInt64_t strips[4], AliHLTInt32_t pos[4]
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.
425 assert( startPos >= 0 );
426 assert( fCurrentStruct != NULL );
428 if (GetLocalSXDev(fCurrentStruct)) // check the direction of the deviation.
430 for (int i = 0; i < 2; ++i)
432 if (((strips[i] >> startPos) & 0x1) == 0x1)
437 for (AliHLTInt32_t j = 1; j < 16; ++j)
439 // We first check the straighter tracklet option, i.e higher momentum.
440 if (startPos - j >= 0 and ((strips[i] >> (startPos - j)) & 0x1) == 0x1)
442 pos[i] = startPos - j;
445 else if (startPos + j < 48 and ((strips[i] >> (startPos + j)) & 0x1) == 0x1)
447 pos[i] = startPos + j;
451 if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
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.
462 for (int i = 2; i < 4; ++i)
464 if (((strips[i] >> endPos) & 0x1) == 0x1)
469 for (AliHLTInt32_t j = 1; j < 16; ++j)
471 if (endPos - j >= 0 and ((strips[i] >> (endPos - j)) & 0x1) == 0x1)
476 else if (endPos + j < 48 and ((strips[i] >> (endPos + j)) & 0x1) == 0x1)
482 if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
487 // Similar logic to the positive deviation case above, but with the
488 // arithmetic inversed.
489 for (int i = 0; i < 2; ++i)
491 if (((strips[i] >> startPos) & 0x1) == 0x1)
496 for (AliHLTInt32_t j = 1; j < 16; ++j)
498 // We first check the straighter tracklet option, i.e higher momentum.
499 if (startPos + j < 48 and ((strips[i] >> (startPos + j)) & 0x1) == 0x1)
501 pos[i] = startPos + j;
504 else if (startPos - j >= 0 and ((strips[i] >> (startPos - j)) & 0x1) == 0x1)
506 pos[i] = startPos - j;
510 if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
513 AliHLTInt32_t endPos = (GetLocalXPos(fCurrentStruct) - GetLocalXDev(fCurrentStruct)) / 2;
514 endPos += 16; // fCurrentStruct strips start at bit 16.
516 for (int i = 2; i < 4; ++i)
518 if (((strips[i] >> endPos) & 0x1) == 0x1)
523 for (AliHLTInt32_t j = 1; j < 16; ++j)
525 if (endPos + j < 48 and ((strips[i] >> (endPos + j)) & 0x1) == 0x1)
530 else if (endPos - j >= 0 and ((strips[i] >> (endPos - j)) & 0x1) == 0x1)
536 if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
542 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindYStrips(
543 AliHLTInt32_t startPos, AliHLTUInt32_t strips[4], AliHLTInt32_t pos[4]
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].
555 assert( startPos >= 0 );
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++)
568 for (AliHLTInt32_t i = (startPos >= 1 ? startPos-1 : 0); i <= 15; i++)
570 if (((strips[n] >> i) & 0x1) == 0x1)
577 for (AliHLTInt32_t i = startPos+1; i >= 0; i--)
579 if (((strips[n] >> i) & 0x1) == 0x1)
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)
592 posNearest[n] = startPos;
597 for (AliHLTInt32_t i = 1; i < 16; ++i)
599 if (((strips[n] >> (startPos + i)) & 0x1) == 0x1)
601 posNearest[n] = startPos + i;
605 else if (((strips[n] >> (startPos - i)) & 0x1) == 0x1)
607 posNearest[n] = startPos - i;
615 // Now select either posUp or posDown, whichever has the most found strips.
616 if (posUpCount >= posDownCount and posUpCount >= posNearestCount)
618 for (AliHLTInt32_t n = 0; n < 4; n++)
621 else if (posDownCount >= posUpCount and posDownCount >= posNearestCount)
623 for (AliHLTInt32_t n = 0; n < 4; n++)
628 for (AliHLTInt32_t n = 0; n < 4; n++)
629 pos[n] = posNearest[n];
634 const AliHLTMUONTriggerRecoLutRow& AliHLTMUONTriggerReconstructor::AliDecoderHandler::GetLutRowX(
635 AliHLTInt32_t xPos, AliHLTUInt8_t chamber
638 // Fetches the appropriate LUT row for a given strip X and Y position.
640 assert( chamber <= 3 );
641 assert( fCurrentCrateId < 16 );
647 locId = fUseLocalId ? GetLocalId(fNextStruct) : fNextLocalIndex;
652 locId = fUseLocalId ? GetLocalId(fCurrentStruct) : fNextLocalIndex-1;
657 locId = fUseLocalId ? GetLocalId(fPrevStruct) : fNextLocalIndex-2;
660 if (locId < 0 or locId >= 16) locId = 0;
661 if (pos < 0 or pos >= 16) pos = 0;
663 return fLookupTable.fRow[fCurrentCrateId][locId][chamber][0][pos];
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
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.
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 );
691 const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(xPos, chamber);
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)
698 if (((xStrips >> (xPos+1)) & 0x1) == 0x1)
700 // Strips fired on both sides of strip at xPos so just use the middle one.
701 hit.fFlags = lut.fIdFlags;
707 // Second strip fired below the one at xPos, so decluster.
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;
717 if (((xStrips >> (xPos+1)) & 0x1) == 0x1)
719 // Second strip fired above the one at xPos, so decluster.
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;
728 // Only strip at xPos fired and neither of its two neighbours.
729 hit.fFlags = lut.fIdFlags;
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)
739 if (((yStrips >> (yPos+1)) & 0x1) == 0x1)
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;
746 // Second strip fired below the one at yPos, so decluster.
748 hit.fX = (fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos-1].fX
749 + fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX) * 0.5;
754 if (((yStrips >> (yPos+1)) & 0x1) == 0x1)
756 // Second strip fired above the one at yPos, so decluster.
758 hit.fX = (fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos+1].fX
759 + fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX) * 0.5;
763 // Only strip at yPos fired and neither of its two neighbours.
764 hit.fX = fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX;
770 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnNewRegionalStructV2(
772 const AliMUONRegionalHeaderStruct* regionalStruct,
773 const AliMUONRegionalScalarsStruct* /*scalars*/,
777 // Reset the local trigger structure pointers, and mark the current regional
778 // structure number and Crate ID.
780 fCurrentRegional = num;
781 fCurrentCrateId = (fUseCrateId ? GetRegionalId(regionalStruct) : num);
782 fPrevStruct = fCurrentStruct = fNextStruct = &fgkNullStruct;
786 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnEndOfRegionalStructV2(
788 const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
789 const AliMUONRegionalScalarsStruct* /*scalars*/,
793 // Process the last local trigger structure.
795 fPrevStruct = fCurrentStruct;
796 fCurrentStruct = fNextStruct;
797 fNextStruct = &fgkNullStruct;
799 // The index numbers for fPrevStruct and fCurrentStruct are calculated from
800 // fNextLocalIndex in ProcessLocalStruct so we need to increment it correctly.
803 ProcessLocalStruct();
807 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
809 const AliMUONLocalInfoStruct* localStruct,
810 const AliMUONLocalScalarsStruct* /*scalars*/
813 // Update pointers and process the current local trigger structure.
816 assert(localStruct != NULL);
818 fPrevStruct = fCurrentStruct;
819 fCurrentStruct = fNextStruct;
820 fNextStruct = localStruct;
821 fNextLocalIndex = iloc;
822 ProcessLocalStruct();
826 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ProcessLocalStruct()
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.
833 assert(fOutputTrigRecs != NULL);
835 // If the current local trigger structure does not have a decision then skip it.
836 if (GetLocalDec(fCurrentStruct) == 0) return;
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;
844 // Check that we will not overflow the output buffer.
845 if (fOutputTrigRecsCount >= fMaxOutputTrigRecs)
847 HLTError("Output buffer has overflowed maximum element count of %d.",
854 AliHLTMUONTriggerRecordStruct& trigger = fOutputTrigRecs[fOutputTrigRecsCount];
856 // Now try find all the fired X and Y strips on all 4 trigger chambers.
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);
869 // hitset indicates which hits on chambers 7 to 10 have been found and filled.
870 bool hitset[4] = {false, false, false, false};
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.
876 for (int i = 0; i < 4; i++)
878 if (stripPosX[i] != -1 and stripPosY[i] != -1)
881 xStrips[i], yStrips[i],
882 stripPosX[i], stripPosY[i],
883 locId[i], i, trigger.fHit[i]
890 trigger.fHit[i] = AliHLTMUONConstants::NilRecHitStruct();
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.
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++)
908 if (stripPosX[i] != -1)
910 const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(stripPosX[i], i);
915 if (stripPosY[i] != -1)
917 const AliHLTMUONTriggerRecoLutRow& lut =
918 fLookupTable.fRow[fCurrentCrateId][locId[i]][i][1][stripPosY[i]];
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)
934 for (int i = 0; i < 4; i++)
936 if (hitset[i]) continue; // Leave the found hits alone.
937 if (stripPosX[i] != -1)
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;
949 else if (stripPosY[i] != -1)
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;
966 // If 4 hits found then check if they are all good, otherwise find the 3
967 // best fitting ones.
970 AliHLTFloat32_t dx = AliMUONConstants::TriggerNonBendingReso();
971 AliHLTFloat32_t dy = AliMUONConstants::TriggerBendingReso();
972 AliHLTMUONCalculations::SigmaX2(dx*dx);
973 AliHLTMUONCalculations::SigmaY2(dy*dy);
975 AliHLTFloat32_t chi2 = AliHLTMUONCalculations::ComputeChi2(trigger, hitset);
976 if (chi2 != -1 and chi2 > 5.*4) // check 5 sigma cut.
978 // Poor fit so look for best 3 points.
980 AliHLTFloat32_t bestchi2 = 1e38;
981 for (int j = 0; j < 4; j++)
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)
994 for (int j = 0; j < 4; j++) hitset[j] = true;
995 hitset[worstHit] = false;
996 trigger.fHit[worstHit] = AliHLTMUONConstants::NilRecHitStruct();
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);
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;
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);
1023 bool trigAdded = false;
1025 if (hitCount >= 3 and
1026 AliHLTMUONCalculations::FitLineToTriggerRecord(trigger, hitset)
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()
1038 trigger.fPx = AliHLTMUONCalculations::Px();
1039 trigger.fPy = AliHLTMUONCalculations::Py();
1040 trigger.fPz = AliHLTMUONCalculations::Pz();
1042 trigger.fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
1043 AliHLTMUONCalculations::Sign(),
1047 fOutputTrigRecsCount++;
1050 else if ((hitset[0] or hitset[1] or hitset[2] or hitset[3])
1051 and not fSuppressPartialTriggers
1054 trigger.fPx = trigger.fPy = trigger.fPz = 0;
1056 trigger.fFlags = AliHLTMUONUtils::PackTriggerRecordFlags(
1061 fOutputTrigRecsCount++;
1065 if (trigAdded and fStoreInfo)
1067 // Allocate or reallocate buffer.
1068 if (fInfoBuffer == NULL)
1072 fInfoBuffer = new AliHLTMUONTrigRecInfoStruct[256];
1076 HLTError("Could not allocate buffer space for debug information.");
1079 fInfoBufferSize = 256;
1081 else if (fInfoBufferCount >= fInfoBufferSize)
1083 AliHLTMUONTrigRecInfoStruct* newbuf = NULL;
1086 newbuf = new AliHLTMUONTrigRecInfoStruct[fInfoBufferSize*2];
1090 HLTError("Could not allocate more buffer space for debug information.");
1093 for (AliHLTUInt32_t i = 0; i < fInfoBufferSize; ++i) newbuf[i] = fInfoBuffer[i];
1094 delete [] fInfoBuffer;
1095 fInfoBuffer = newbuf;
1096 fInfoBufferSize = fInfoBufferSize*2;
1099 fInfoBuffer[fInfoBufferCount].fTrigRecId = trigger.fId;
1100 for (int i = 0; i < 4; ++i)
1102 if (trigger.fHit[i] != AliHLTMUONConstants::NilRecHitStruct())
1104 fInfoBuffer[fInfoBufferCount].fDetElemId[i] =
1105 AliHLTMUONUtils::GetDetElemIdFromFlags(trigger.fHit[i].fFlags);
1109 fInfoBuffer[fInfoBufferCount].fDetElemId[i] = -1;
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;
1122 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnError(
1123 ErrorCode code, const void* location
1126 /// Logs an error message if there was a decoding problem with the DDL payload.
1128 long bytepos = long(location) - long(fBufferStart);
1129 if (code == kWrongEventType)
1131 fHadWrongEventTypeError = true;
1133 /// Do not generate an error message if the fDontPrintWrongEventError option is set.
1134 if (fDontPrintWrongEventError) return;
1138 fHadNonWrongEventTypeError = true;
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
1149 HLTError("There is a problem with decoding the raw data. %s (Error code: %d, at byte %d)",
1150 ErrorCodeToMessage(code), code, bytepos