]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/AliHLTMUONUtils.cxx
Filling out AliHLTMUONDigitPublisherComponent code to generate dimuon raw data on...
[u/mrichter/AliRoot.git] / HLT / MUON / AliHLTMUONUtils.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///
19 /// @file   AliHLTMUONUtils.cxx
20 /// @author Artur Szostak <artursz@iafrica.com>
21 /// @date   17 May 2007
22 /// @brief  Implementation of AliHLTMUONUtils utility routines.
23 ///
24
25 #include "AliHLTMUONUtils.h"
26 #include "AliHLTMUONConstants.h"
27 #include "AliHLTMUONTriggerRecordsBlockStruct.h"
28 #include "AliHLTMUONTrigRecsDebugBlockStruct.h"
29 #include "AliHLTMUONTriggerChannelsBlockStruct.h"
30 #include "AliHLTMUONRecHitsBlockStruct.h"
31 #include "AliHLTMUONClustersBlockStruct.h"
32 #include "AliHLTMUONChannelsBlockStruct.h"
33 #include "AliHLTMUONMansoTracksBlockStruct.h"
34 #include "AliHLTMUONMansoCandidatesBlockStruct.h"
35 #include "AliHLTMUONSinglesDecisionBlockStruct.h"
36 #include "AliHLTMUONPairsDecisionBlockStruct.h"
37 #include "AliMUONTrackerDDLDecoderEventHandler.h"
38 #include <cstring>
39 #include <cmath>
40 #include <cassert>
41
42
43 AliHLTUInt32_t AliHLTMUONUtils::PackTriggerRecordFlags(
44                 AliHLTMUONParticleSign sign, const bool hitset[4]
45         )
46 {
47         ///
48         /// This packs the given parameters into the bits of a word appropriate
49         /// for AliHLTMUONTriggerRecordStruct::fFlags.
50         /// @param sign    The particle sign.
51         /// @param hitset  Flags to indicate if the corresponding fHits[i] elements
52         ///                was set/filled.
53         /// @return  Returns the 32 bit packed word.
54         ///
55         
56         AliHLTUInt32_t flags;
57         switch (sign)
58         {
59         case kSignMinus: flags = 0x80000000; break;
60         case kSignPlus:  flags = 0x40000000; break;
61         default:         flags = 0x00000000; break;
62         }
63
64         return flags | (hitset[0] ? 0x1 : 0) | (hitset[1] ? 0x2 : 0)
65                 | (hitset[2] ? 0x4 : 0) | (hitset[3] ? 0x8 : 0);
66 }
67
68
69 void AliHLTMUONUtils::UnpackTriggerRecordFlags(
70                 AliHLTUInt32_t flags, AliHLTMUONParticleSign& sign, bool hitset[4]
71         )
72 {
73         ///
74         /// This unpacks the AliHLTMUONTriggerRecordStruct::fFlags bits into
75         /// its component fields.
76         /// @param flags  The flags from an AliHLTMUONTriggerRecordStruct structure.
77         /// @param sign    Sets this to the particle sign.
78         /// @param hitset  Sets the array elements to indicate if the corresponding
79         ///                fHits[i] element was set/filled.
80         ///
81         
82         AliHLTUInt32_t signbits = flags & 0xC0000000;
83         switch (signbits)
84         {
85         case 0x80000000: sign = kSignMinus;   break;
86         case 0x40000000: sign = kSignPlus;    break;
87         default:         sign = kSignUnknown; break;
88         }
89         hitset[0] = (flags & 0x1) == 0x1;
90         hitset[1] = (flags & 0x2) == 0x2;
91         hitset[2] = (flags & 0x4) == 0x4;
92         hitset[3] = (flags & 0x8) == 0x8;
93 }
94
95
96 AliHLTUInt32_t AliHLTMUONUtils::PackTrackDecisionBits(bool highPt, bool lowPt)
97 {
98         ///
99         /// This packs the given parameters into the bits of a word appropriate
100         /// for AliHLTMUONTrackDecisionStruct::fTriggerBits.
101         /// @param highPt  Has the track passed the high pt cut.
102         /// @param lowPt   Has the track passed the low pt cut.
103         /// @return  Returns the 32 bit packed word.
104         ///
105         
106         return (highPt ? 0x2 : 0) | (lowPt ? 0x1 : 0);
107 }
108
109
110 void AliHLTMUONUtils::UnpackTrackDecisionBits(
111                 AliHLTUInt32_t bits, bool& highPt, bool& lowPt
112         )
113 {
114         ///
115         /// This unpacks the AliHLTMUONTrackDecisionStruct::fTriggerBits bits into
116         /// its component fields.
117         /// @param bits  The trigger bits from an AliHLTMUONTrackDecisionStruct
118         ///              structure.
119         /// @param highPt Sets this to the value of the high pt cut bit.
120         /// @param lowPt  Sets this to the value of the low pt cut bit.
121         ///
122         
123         lowPt  = (bits & 0x1) == 0x1;
124         highPt = (bits & 0x2) == 0x2;
125 }
126
127
128 AliHLTUInt32_t AliHLTMUONUtils::PackPairDecisionBits(
129                 bool highMass, bool lowMass, bool unlike,
130                 AliHLTUInt8_t highPtCount, AliHLTUInt8_t lowPtCount
131         )
132 {
133         ///
134         /// This packs the given parameters into the bits of a word appropriate
135         /// for AliHLTMUONPairDecisionStruct::fTriggerBits.
136         ///
137         /// @param highMass Has the track pair passed the high invariant mass cut.
138         /// @param lowMass  Has the track pair passed the low invariant mass cut.
139         /// @param unlike   Does the track pair have unlike signs.
140         /// @param highPtCount The number of tracks that passed the high pt cut
141         ///                    in the pair.
142         /// @param lowPtCount  The number of tracks that passed the low pt cut
143         ///                    in the pair.
144         /// @return  Returns the 32 bit packed word.
145         ///
146         /// Note: Must have highPtCount + lowPtCount <= 2 and unlike == true if
147         /// highMass or lowMass is true.
148         ///
149         
150         assert( highPtCount + lowPtCount <= 2 );
151         // highMass and lowMass must be false if unlike is false:
152         assert( not unlike ? (highMass == false and lowMass == false) : true );
153         
154         return (highMass ? 0x40 : 0) | (lowMass ? 0x20 : 0) | (unlike ? 0x10 : 0)
155                 | ((highPtCount & 0x3) << 2) | (lowPtCount & 0x3);
156 }
157
158
159 void AliHLTMUONUtils::UnpackPairDecisionBits(
160                 AliHLTUInt32_t bits, bool& highMass, bool& lowMass, bool& unlike,
161                 AliHLTUInt8_t& highPtCount, AliHLTUInt8_t& lowPtCount
162         )
163 {
164         ///
165         /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
166         /// its component fields.
167         /// @param bits  The trigger bits from an AliHLTMUONPairDecisionStruct
168         ///              structure.
169         /// @param highMass Sets this to the value of the high invariant mass cut bit.
170         /// @param lowMass  Sets this to the value of the low invariant mass cut bit.
171         /// @param unlike   Sets this if the pair is unlike sign.
172         /// @param highPtCount Sets this to the high pt count bits.
173         /// @param lowPtCount  Sets this to the low pt count bits.
174         ///
175         
176         highMass = (bits & 0x40) == 0x40;
177         lowMass  = (bits & 0x20) == 0x20;
178         unlike   = (bits & 0x10) == 0x10;
179         highPtCount = (bits & 0xC) >> 2;
180         lowPtCount = bits & 0x3;
181 }
182
183
184 AliHLTUInt32_t AliHLTMUONUtils::PackSpecBits(
185                 const bool ddl[22]
186         )
187 {
188         ///
189         /// This packs the given parameters into the 32bit Pub/Sub specification
190         /// word in the data block descriptor.
191         ///
192         /// @param ddl  The list of DDLs forming part of the readout. ddl[0]
193         ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
194         ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
195         ///             trigger DDLs 2816 and 2817 respectively.
196         /// @return  Returns the 32 bit packed specification word.
197         ///
198         
199         // Pack the bits into the following format:
200         //   bit:   [        31 - 22        ][     21     ][     20     ][  19 - 0 ]
201         //   field: [ reserved, set to zero ][ TRGDDL2817 ][ TRGDDL2816 ][ TRKDDLS ]
202         // Meaning of field acronyms:
203         //   TRGDDL2816 - Trigger DDL number 2816.
204         //   TRGDDL2817 - Trigger DDL number 2817.
205         //   TRKDDLS - Tracking DDL flags where bit 0 will be for DDL number 2560,
206         //             bit 1 for DDL no. 2561 etc. up to bit 19 which is for DDL 2579.
207         AliHLTUInt32_t bits = 0;
208         for (int i = 0; i < 22; i++)
209                 bits |= (ddl[i] ? 0x1 : 0x0) << i;
210         return bits;
211 }
212
213
214 void AliHLTMUONUtils::UnpackSpecBits(
215                 AliHLTUInt32_t bits, bool ddl[22]
216         )
217 {
218         ///
219         /// This unpacks the AliHLTMUONPairDecisionStruct::fTriggerBits bits into
220         /// its component fields.
221         /// @param bits  The Pub/Sub specification word from a data block descriptor.
222         /// @param ddl  The output list of DDLs forming part of the readout. ddl[0]
223         ///             indicates DDL number 2560, ddl[1] is for DDL 2561 and so
224         ///             on up to ddl[19]. ddl[20] and ddl[21] will be for the
225         ///             trigger DDLs 2816 and 2817 respectively.
226         ///
227         
228         // Perform the inverse operation of PackSpecBits.
229         for (int i = 0; i < 22; i++)
230                 ddl[i] = ((bits >> i) & 0x1) == 1;
231 }
232
233
234 AliHLTInt32_t AliHLTMUONUtils::DDLNumberToEquipId(AliHLTInt32_t ddlNo)
235 {
236         ///
237         /// This method converts the DDL number for the muon spectrometer in the
238         /// range [0..21] to the equipment ID number.
239         /// @param ddlNo  The DDL number in the range [0..21].
240         /// @return  Returns the equipment ID number or -1 if ddlNo was invalid.
241         ///
242         
243         if (0 <= ddlNo and ddlNo <= 19)
244         {
245                 return 2560 + ddlNo;
246         }
247         else if (20 <= ddlNo and ddlNo <= 21)
248         {
249                 return 2816 + (ddlNo - 20);
250         }
251         else
252         {
253                 return -1;
254         }
255 }
256
257
258 AliHLTInt32_t AliHLTMUONUtils::EquipIdToDDLNumber(AliHLTInt32_t id)
259 {
260         ///
261         /// This method converts the equipment ID number for a muon spectrometer
262         /// DDL to the DDL number in the range [0..21].
263         /// @param id  The equipment ID of the DDL.
264         /// @return  Returns the DDL number in the range [0..21] or -1 if the
265         ///          equipment ID was invalid.
266         ///
267         
268         if (2560 <= id and id <= 2560+19)
269         {
270                 return id - 2560;
271         }
272         else if (2816 <= id and id <= 2817)
273         {
274                 return id - 2816 + 20;
275         }
276         else
277         {
278                 return -1;
279         }
280 }
281
282
283 AliHLTInt32_t AliHLTMUONUtils::SpecToEquipId(AliHLTUInt32_t spec)
284 {
285         ///
286         /// This method converts a 32 bit data block specification for a MUON-HLT
287         /// data block into its corresponding DDL equipment ID number.
288         /// It is assumed that the specification is for a data block comming from
289         /// a single DDL source. If more than one DDL contributed to the data block
290         /// then -1 is returned.
291         /// @param spec  The 32 bit specification for a data block.
292         /// @return  Returns the equipment ID corresponding to the specification
293         ///          or -1 if the specification was invalid.
294         ///
295         
296         for (AliHLTInt32_t ddlNo = 0; ddlNo < 20; ddlNo++)
297         {
298                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
299                         return ddlNo + 2560;
300         }
301         for (AliHLTInt32_t ddlNo = 20; ddlNo < 22; ddlNo++)
302         {
303                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
304                         return ddlNo - 20 + 2816;
305         }
306         return -1;
307 }
308
309
310 AliHLTUInt32_t AliHLTMUONUtils::EquipIdToSpec(AliHLTInt32_t id)
311 {
312         ///
313         /// This method converts a equipment ID number for a DDL into its corresponding
314         /// 32 bit data block specification for the MUON-HLT.
315         /// @param id  The equipment ID number of the DDL.
316         /// @return  Returns the 32 bit data block specification or 0x0 if the
317         ///          equipment ID was invalid.
318         ///
319         
320         if (2560 <= id and id <= 2560+19)
321         {
322                 return 0x1 << (id - 2560);
323         }
324         else if (2816 <= id and id <= 2817)
325         {
326                 return 0x1 << (id - 2816 + 20);
327         }
328         else
329         {
330                 return 0x0;
331         }
332 }
333
334
335 AliHLTInt32_t AliHLTMUONUtils::SpecToDDLNumber(AliHLTUInt32_t spec)
336 {
337         ///
338         /// This method converts a 32 bit data block specification for a MUON-HLT
339         /// data block into its corresponding DDL number in the range [0..21].
340         /// It is assumed that the specification is for a data block comming from
341         /// a single DDL source. If more than one DDL contributed to the data block
342         /// then -1 is returned.
343         /// @param spec  The 32 bit specification for a data block.
344         /// @return  Returns the corresponding DDL number for the specification
345         ///          or -1 if the specification was invalid.
346         ///
347         
348         for (AliHLTInt32_t ddlNo = 0; ddlNo < 22; ddlNo++)
349         {
350                 if (spec == AliHLTUInt32_t(0x1 << ddlNo))
351                         return ddlNo;
352         }
353         return -1;
354 }
355
356
357 AliHLTUInt32_t AliHLTMUONUtils::DDLNumberToSpec(AliHLTInt32_t ddlNo)
358 {
359         ///
360         /// This method converts a DDL number in the range [0..21] into its
361         /// corresponding 32 bit data block specification for the MUON-HLT.
362         /// @param ddlNo  The equipment ID number of the DDL.
363         /// @return  Returns the 32 bit data block specification or 0x0 if the
364         ///          DDL number was invalid (out of range).
365         ///
366         
367         if (0 <= ddlNo and ddlNo <= 21)
368         {
369                 return 0x1 << ddlNo;
370         }
371         else
372         {
373                 return 0x0;
374         }
375 }
376
377
378 AliHLTMUONDataBlockType AliHLTMUONUtils::ParseCommandLineTypeString(const char* type)
379 {
380         /// Parses the string containing the type name of a dHLT data block and
381         /// returns the corresponding AliHLTMUONDataBlockType value.
382         /// \param  type  The string containing the type name.
383         /// \returns  The data block type or kUnknownDataBlock if the type name
384         ///      is invalid.
385
386         if (strcmp(type, "trigrecs") == 0)
387         {
388                 return kTriggerRecordsDataBlock;
389         }
390         else if (strcmp(type, "trigrecsdebug") == 0)
391         {
392                 return kTrigRecsDebugDataBlock;
393         }
394         else if (strcmp(type, "trigchannels") == 0)
395         {
396                 return kTriggerChannelsDataBlock;
397         }
398         else if (strcmp(type, "rechits") == 0)
399         {
400                 return kRecHitsDataBlock;
401         }
402         else if (strcmp(type,"channels") == 0)
403         {
404                 return kChannelsDataBlock;
405         }
406         else if (strcmp(type,"clusters") == 0)
407         {
408                 return kClustersDataBlock;
409         }
410         else if (strcmp(type, "mansotracks") == 0)
411         {
412                 return kMansoTracksDataBlock;
413         }
414         else if (strcmp(type, "mansocandidates") == 0)
415         {
416                 return kMansoCandidatesDataBlock;
417         }
418         else if (strcmp(type, "singlesdecision") == 0)
419         {
420                 return kSinglesDecisionDataBlock;
421         }
422         else if (strcmp(type, "pairsdecision") == 0)
423         {
424                 return kPairsDecisionDataBlock;
425         }
426         
427         return kUnknownDataBlock;
428 }
429
430
431 const char* AliHLTMUONUtils::DataBlockTypeToString(AliHLTMUONDataBlockType type)
432 {
433         /// Converts a type ID to a type string compatible with
434         /// HLT data types.
435         
436         static char str[kAliHLTComponentDataTypefIDsize+1];
437         AliHLTComponentDataType t;
438         switch (type)
439         {
440         case kTriggerRecordsDataBlock:
441                 t = AliHLTMUONConstants::TriggerRecordsBlockDataType();
442                 break;
443         case kTrigRecsDebugDataBlock:
444                 t = AliHLTMUONConstants::TrigRecsDebugBlockDataType();
445                 break;
446         case kTriggerChannelsDataBlock:
447                 t = AliHLTMUONConstants::TriggerChannelBlockDataType();
448                 break;
449         case kRecHitsDataBlock:
450                 t = AliHLTMUONConstants::RecHitsBlockDataType();
451                 break;
452         case kClustersDataBlock:
453                 t = AliHLTMUONConstants::ClusterBlockDataType();
454                 break;
455         case kChannelsDataBlock:
456                 t = AliHLTMUONConstants::ChannelBlockDataType();
457                 break;
458         case kMansoTracksDataBlock:
459                 t = AliHLTMUONConstants::MansoTracksBlockDataType();
460                 break;
461         case kMansoCandidatesDataBlock:
462                 t = AliHLTMUONConstants::MansoCandidatesBlockDataType();
463                 break;
464         case kSinglesDecisionDataBlock:
465                 t = AliHLTMUONConstants::SinglesDecisionBlockDataType();
466                 break;
467         case kPairsDecisionDataBlock:
468                 t = AliHLTMUONConstants::PairsDecisionBlockDataType();
469                 break;
470         default:
471                 return "UNKNOWN";
472         }
473         memcpy(&str, &t.fID, kAliHLTComponentDataTypefIDsize);
474         // Must insert the NULL character to make this an ANSI C string.
475         str[kAliHLTComponentDataTypefIDsize] = '\0';
476         return &str[0];
477 }
478
479
480 const char* AliHLTMUONUtils::FailureReasonToString(WhyNotValid reason)
481 {
482         /// This method converts the WhyNotValid enumeration to a string representation.
483         
484         switch (reason)
485         {
486         case kNoReason: return "kNoReason";
487         case kHeaderContainsWrongType: return "kHeaderContainsWrongType";
488         case kHeaderContainsWrongRecordWidth: return "kHeaderContainsWrongRecordWidth";
489         case kInvalidIdValue: return "kInvalidIdValue";
490         case kInvalidTriggerIdValue: return "kInvalidTriggerIdValue";
491         case kInvalidTrackIdValue: return "kInvalidTrackIdValue";
492         case kReservedBitsNotZero: return "kReservedBitsNotZero";
493         case kParticleSignBitsNotValid: return "kParticleSignBitsNotValid";
494         case kHitNotMarkedAsNil: return "kHitNotMarkedAsNil";
495         case kInvalidDetElementNumber: return "kInvalidDetElementNumber";
496         case kHitIsNil: return "kHitIsNil";
497         case kInvalidChannelCount: return "kInvalidChannelCount";
498         case kInvalidBusPatchId: return "kInvalidBusPatchId";
499         case kInvalidManuId: return "kInvalidManuId";
500         case kInvalidChannelAddress: return "kInvalidChannelAddress";
501         case kInvalidSignal: return "kInvalidSignal";
502         case kDataWordDifferent: return "kDataWordDifferent";
503         case kChiSquareInvalid: return "kChiSquareInvalid";
504         case kMomentumVectorNotZero: return "kMomentumVectorNotZero";
505         case kRoiRadiusInvalid: return "kRoiRadiusInvalid";
506         case kHitNotWithinRoi: return "kHitNotWithinRoi";
507         case kPtValueNotValid: return "kPtValueNotValid";
508         case kPairTrackIdsAreIdentical: return "kPairTrackIdsAreIdentical";
509         case kMassValueNotValid: return "kMassValueNotValid";
510         case kLowPtCountInvalid: return "kLowPtCountInvalid";
511         case kHighPtCountInvalid: return "kHighPtCountInvalid";
512         case kFoundDuplicateIDs: return "kFoundDuplicateIDs";
513         case kFoundDuplicateHits: return "kFoundDuplicateHits";
514         case kFoundDuplicateTriggers: return "kFoundDuplicateTriggers";
515         default: return "INVALID";
516         }
517 }
518
519
520 const char* AliHLTMUONUtils::FailureReasonToMessage(WhyNotValid reason)
521 {
522         /// This method returns a string containing a user readable message explaining
523         /// the reason for failure described by the WhyNotValid enumeration.
524         
525         switch (reason)
526         {
527         case kNoReason:
528                 return "There was no problem with the data block.";
529         case kHeaderContainsWrongType:
530                 return "The common data header contains an incorrect type"
531                         " identifier.";
532         case kHeaderContainsWrongRecordWidth:
533                 return "The common data header contains an incorrect data"
534                         " record width.";
535         case kInvalidIdValue:
536                 return "The structure identifier does not have a valid value.";
537         case kInvalidTriggerIdValue:
538                 return "The trigger structure identifier does not have a valid"
539                         " value.";
540         case kInvalidTrackIdValue:
541                 return "The track structure identifier does not have a valid"
542                         " value.";
543         case kReservedBitsNotZero:
544                 return "Reserved bits have not been set to zero.";
545         case kParticleSignBitsNotValid:
546                 return "The particle sign bits are not a valid value.";
547         case kHitNotMarkedAsNil:
548                 return "A hit was marked as not found, but the corresponding hit"
549                         " structure was not set to nil.";
550         case kInvalidDetElementNumber:
551                 return "An invalid detector element ID was found.";
552         case kHitIsNil:
553                 return "The hit cannot be set to a nil value.";
554         case kInvalidChannelCount:
555                 return "The number of channels indicated is zero or outside"
556                         " the valid range.";
557         case kInvalidBusPatchId:
558                 return "The bus patch identifier is outside the valid range.";
559         case kInvalidManuId:
560                 return "The MANU identifier is outside the valid range.";
561         case kInvalidChannelAddress:
562                 return "The MANU channel address is outside the valid range.";
563         case kInvalidSignal:
564                 return "The ADC signal value is outside the valid range.";
565         case kDataWordDifferent:
566                 return "The raw data word is different from the unpacked values.";
567         case kChiSquareInvalid:
568                 return "The chi squared value must be a positive value or -1"
569                         " indicating a fitting error.";
570         case kMomentumVectorNotZero:
571                 return "The chi sqaured value is set to -1 indicating momentum"
572                         " was not fitted, but the momentum vector was not zero.";
573         case kRoiRadiusInvalid:
574                 return "The region of interest radius is invalid.";
575         case kHitNotWithinRoi:
576                 return "A tracks hit is not within the corresponding region"
577                         " of interest.";
578         case kPtValueNotValid:
579                 return "The pT value is not positive, nor -1 indicating an"
580                         " invalid value.";
581         case kPairTrackIdsAreIdentical:
582                 return "The track identifiers of the track pair are identical.";
583         case kMassValueNotValid:
584                 return "The invariant mass value is not positive, nor -1"
585                         " indicating an invalid value.";
586         case kLowPtCountInvalid:
587                 return "The low pT trigger count is greater than 2,"
588                         " which is invalid.";
589         case kHighPtCountInvalid:
590                 return "The high pT trigger count is greater than 2,"
591                         " which is invalid.";
592         case kFoundDuplicateIDs:
593                 return "Found duplicate data record identifiers, but they"
594                         " should all be unique.";
595         case kFoundDuplicateHits:
596                 return "Found duplicate hit structures, but they should all"
597                         " be unique.";
598         case kFoundDuplicateTriggers:
599                 return "Found duplicate trigger decisions.";
600         default:
601                 return "UNKNOWN REASON CODE";
602         }
603 }
604
605
606 bool AliHLTMUONUtils::RecordNumberWasSet(WhyNotValid reason)
607 {
608         /// Returns true if the \em recordNum in the corresponding IntegrityOk method
609         /// would have been set, if it returned false and a reason was set.
610         /// This helper method makes it easy to test if the \em recordNum parameter
611         /// is filled with a valid value or not.
612         /// \param reason  The reason code as returned by the IntegrityOk method.
613         /// \returns  true if the \em recordNum parameter was set for the given
614         ///      reason code.
615         
616         switch (reason)
617         {
618         case kInvalidIdValue:
619         case kInvalidTriggerIdValue:
620         case kInvalidTrackIdValue:
621         case kReservedBitsNotZero:
622         case kParticleSignBitsNotValid:
623         case kHitNotMarkedAsNil:
624         case kInvalidDetElementNumber:
625         case kHitIsNil:
626         case kInvalidChannelCount:
627         case kInvalidBusPatchId:
628         case kInvalidManuId:
629         case kInvalidChannelAddress:
630         case kInvalidSignal:
631         case kDataWordDifferent:
632         case kChiSquareInvalid:
633         case kPtValueNotValid:
634         case kPairTrackIdsAreIdentical:
635         case kMassValueNotValid:
636         case kLowPtCountInvalid:
637         case kHighPtCountInvalid:
638                 return true;
639         default: return false;
640         }
641 }
642
643
644 bool AliHLTMUONUtils::HeaderOk(
645                 const AliHLTMUONTriggerRecordsBlockStruct& block,
646                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
647         )
648 {
649         /// Method used to check if the header information corresponds to the
650         /// supposed type of the raw dHLT data block.
651         /// [in]  \param block  The data block to check.
652         /// [out] \param reason  If this is not NULL, then it is assumed to point
653         ///      to an array of at least 'reasonCount' number of elements. It will
654         ///      be filled with the reason codes describing why the header is not
655         ///      valid.
656         /// [in/out] \param reasonCount  This should initially specify the size of
657         ///      the array pointed to by 'reason'. It will be filled with the number
658         ///      of items actually filled into the reason array upon exit from this
659         ///      method.
660         /// \returns  true if there is no problem with the header and false otherwise.
661         
662         AliHLTUInt32_t maxCount = reasonCount;
663         reasonCount = 0;
664         bool result = true;
665         
666         // The block must have the correct type.
667         if (block.fHeader.fType != kTriggerRecordsDataBlock)
668         {
669                 if (reason != NULL and reasonCount < maxCount)
670                 {
671                         reason[reasonCount] = kHeaderContainsWrongType;
672                         reasonCount++;
673                 }
674                 result = false;
675         }
676         
677         // The block's record width must be the correct size.
678         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerRecordStruct))
679         {
680                 if (reason != NULL and reasonCount < maxCount)
681                 {
682                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
683                         reasonCount++;
684                 }
685                 result = false;
686         }
687         
688         return result;
689 }
690
691
692 bool AliHLTMUONUtils::HeaderOk(
693                 const AliHLTMUONTrigRecsDebugBlockStruct& block,
694                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
695         )
696 {
697         /// Method used to check if the header information corresponds to the
698         /// supposed type of the raw dHLT data block.
699         /// [in]  \param block  The data block to check.
700         /// [out] \param reason  If this is not NULL, then it is assumed to point
701         ///      to an array of at least 'reasonCount' number of elements. It will
702         ///      be filled with the reason codes describing why the header is not
703         ///      valid.
704         /// [in/out] \param reasonCount  This should initially specify the size of
705         ///      the array pointed to by 'reason'. It will be filled with the number
706         ///      of items actually filled into the reason array upon exit from this
707         ///      method.
708         /// \returns  true if there is no problem with the header and false otherwise.
709         
710         AliHLTUInt32_t maxCount = reasonCount;
711         reasonCount = 0;
712         bool result = true;
713         
714         // The block must have the correct type.
715         if (block.fHeader.fType != kTrigRecsDebugDataBlock)
716         {
717                 if (reason != NULL and reasonCount < maxCount)
718                 {
719                         reason[reasonCount] = kHeaderContainsWrongType;
720                         reasonCount++;
721                 }
722                 result = false;
723         }
724         
725         // The block's record width must be the correct size.
726         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrigRecInfoStruct))
727         {
728                 if (reason != NULL and reasonCount < maxCount)
729                 {
730                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
731                         reasonCount++;
732                 }
733                 result = false;
734         }
735         
736         return result;
737 }
738
739
740 bool AliHLTMUONUtils::HeaderOk(
741                 const AliHLTMUONTriggerChannelsBlockStruct& block,
742                 WhyNotValid* reason
743         )
744 {
745         /// Method used to check if the header information corresponds to the
746         /// supposed type of the raw dHLT data block.
747         /// [in]  \param block  The data block to check.
748         /// [out] \param reason  If this is not NULL, then it will be filled with
749         ///      the reason code describing why the header is not valid, if and
750         ///      only if a problem is found with the data.
751         /// \returns  true if there is no problem with the header and false otherwise.
752         
753         // The block must have the correct type.
754         if (block.fHeader.fType != kTriggerChannelsDataBlock)
755         {
756                 if (reason != NULL) *reason = kHeaderContainsWrongType;
757                 return false;
758         }
759         
760         // The block's record width must be the correct size.
761         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTriggerChannelStruct))
762         {
763                 if (reason != NULL) *reason = kHeaderContainsWrongRecordWidth;
764                 return false;
765         }
766         
767         return true;
768 }
769
770
771 bool AliHLTMUONUtils::HeaderOk(
772                 const AliHLTMUONRecHitsBlockStruct& block,
773                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
774         )
775 {
776         /// Method used to check if the header information corresponds to the
777         /// supposed type of the raw dHLT data block.
778         /// [in]  \param block  The data block to check.
779         /// [out] \param reason  If this is not NULL, then it is assumed to point
780         ///      to an array of at least 'reasonCount' number of elements. It will
781         ///      be filled with the reason codes describing why the header is not
782         ///      valid.
783         /// [in/out] \param reasonCount  This should initially specify the size of
784         ///      the array pointed to by 'reason'. It will be filled with the number
785         ///      of items actually filled into the reason array upon exit from this
786         ///      method.
787         /// \returns  true if there is no problem with the header and false otherwise.
788         
789         AliHLTUInt32_t maxCount = reasonCount;
790         reasonCount = 0;
791         bool result = true;
792         
793         // The block must have the correct type.
794         if (block.fHeader.fType != kRecHitsDataBlock)
795         {
796                 if (reason != NULL and reasonCount < maxCount)
797                 {
798                         reason[reasonCount] = kHeaderContainsWrongType;
799                         reasonCount++;
800                 }
801                 result = false;
802         }
803         
804         // The block's record width must be the correct size.
805         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONRecHitStruct))
806         {
807                 if (reason != NULL and reasonCount < maxCount)
808                 {
809                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
810                         reasonCount++;
811                 }
812                 result = false;
813         }
814         
815         return result;
816 }
817
818
819 bool AliHLTMUONUtils::HeaderOk(
820                 const AliHLTMUONClustersBlockStruct& block,
821                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
822         )
823 {
824         /// Method used to check if the header information corresponds to the
825         /// supposed type of the raw dHLT data block.
826         /// [in]  \param block  The data block to check.
827         /// [out] \param reason  If this is not NULL, then it is assumed to point
828         ///      to an array of at least 'reasonCount' number of elements. It will
829         ///      be filled with the reason codes describing why the header is not
830         ///      valid.
831         /// [in/out] \param reasonCount  This should initially specify the size of
832         ///      the array pointed to by 'reason'. It will be filled with the number
833         ///      of items actually filled into the reason array upon exit from this
834         ///      method.
835         /// \returns  true if there is no problem with the header and false otherwise.
836         
837         AliHLTUInt32_t maxCount = reasonCount;
838         reasonCount = 0;
839         bool result = true;
840         
841         // The block must have the correct type.
842         if (block.fHeader.fType != kClustersDataBlock)
843         {
844                 if (reason != NULL and reasonCount < maxCount)
845                 {
846                         reason[reasonCount] = kHeaderContainsWrongType;
847                         reasonCount++;
848                 }
849                 result = false;
850         }
851         
852         // The block's record width must be the correct size.
853         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONClusterStruct))
854         {
855                 if (reason != NULL and reasonCount < maxCount)
856                 {
857                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
858                         reasonCount++;
859                 }
860                 result = false;
861         }
862         
863         return result;
864 }
865
866
867 bool AliHLTMUONUtils::HeaderOk(
868                 const AliHLTMUONChannelsBlockStruct& block,
869                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
870         )
871 {
872         /// Method used to check if the header information corresponds to the
873         /// supposed type of the raw dHLT data block.
874         /// [in]  \param block  The data block to check.
875         /// [out] \param reason  If this is not NULL, then it is assumed to point
876         ///      to an array of at least 'reasonCount' number of elements. It will
877         ///      be filled with the reason codes describing why the header is not
878         ///      valid.
879         /// [in/out] \param reasonCount  This should initially specify the size of
880         ///      the array pointed to by 'reason'. It will be filled with the number
881         ///      of items actually filled into the reason array upon exit from this
882         ///      method.
883         /// \returns  true if there is no problem with the header and false otherwise.
884         
885         AliHLTUInt32_t maxCount = reasonCount;
886         reasonCount = 0;
887         bool result = true;
888         
889         // The block must have the correct type.
890         if (block.fHeader.fType != kChannelsDataBlock)
891         {
892                 if (reason != NULL and reasonCount < maxCount)
893                 {
894                         reason[reasonCount] = kHeaderContainsWrongType;
895                         reasonCount++;
896                 }
897                 result = false;
898         }
899         
900         // The block's record width must be the correct size.
901         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONChannelStruct))
902         {
903                 if (reason != NULL and reasonCount < maxCount)
904                 {
905                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
906                         reasonCount++;
907                 }
908                 result = false;
909         }
910         
911         return result;
912 }
913
914
915 bool AliHLTMUONUtils::HeaderOk(
916                 const AliHLTMUONMansoTracksBlockStruct& block,
917                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
918         )
919 {
920         /// Method used to check if the header information corresponds to the
921         /// supposed type of the raw dHLT data block.
922         /// [in]  \param block  The data block to check.
923         /// [out] \param reason  If this is not NULL, then it is assumed to point
924         ///      to an array of at least 'reasonCount' number of elements. It will
925         ///      be filled with the reason codes describing why the header is not
926         ///      valid.
927         /// [in/out] \param reasonCount  This should initially specify the size of
928         ///      the array pointed to by 'reason'. It will be filled with the number
929         ///      of items actually filled into the reason array upon exit from this
930         ///      method.
931         /// \returns  true if there is no problem with the header and false otherwise.
932         
933         AliHLTUInt32_t maxCount = reasonCount;
934         reasonCount = 0;
935         bool result = true;
936         
937         // The block must have the correct type.
938         if (block.fHeader.fType != kMansoTracksDataBlock)
939         {
940                 if (reason != NULL and reasonCount < maxCount)
941                 {
942                         reason[reasonCount] = kHeaderContainsWrongType;
943                         reasonCount++;
944                 }
945                 result = false;
946         }
947         
948         // The block's record width must be the correct size.
949         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoTrackStruct))
950         {
951                 if (reason != NULL and reasonCount < maxCount)
952                 {
953                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
954                         reasonCount++;
955                 }
956                 result = false;
957         }
958         
959         return result;
960 }
961
962
963 bool AliHLTMUONUtils::HeaderOk(
964                 const AliHLTMUONMansoCandidatesBlockStruct& block,
965                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
966         )
967 {
968         /// Method used to check if the header information corresponds to the
969         /// supposed type of the raw dHLT data block.
970         /// [in]  \param block  The data block to check.
971         /// [out] \param reason  If this is not NULL, then it is assumed to point
972         ///      to an array of at least 'reasonCount' number of elements. It will
973         ///      be filled with the reason codes describing why the header is not
974         ///      valid.
975         /// [in/out] \param reasonCount  This should initially specify the size of
976         ///      the array pointed to by 'reason'. It will be filled with the number
977         ///      of items actually filled into the reason array upon exit from this
978         ///      method.
979         /// \returns  true if there is no problem with the header and false otherwise.
980         
981         AliHLTUInt32_t maxCount = reasonCount;
982         reasonCount = 0;
983         bool result = true;
984         
985         // The block must have the correct type.
986         if (block.fHeader.fType != kMansoCandidatesDataBlock)
987         {
988                 if (reason != NULL and reasonCount < maxCount)
989                 {
990                         reason[reasonCount] = kHeaderContainsWrongType;
991                         reasonCount++;
992                 }
993                 result = false;
994         }
995         
996         // The block's record width must be the correct size.
997         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONMansoCandidateStruct))
998         {
999                 if (reason != NULL and reasonCount < maxCount)
1000                 {
1001                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
1002                         reasonCount++;
1003                 }
1004                 result = false;
1005         }
1006         
1007         return result;
1008 }
1009
1010
1011 bool AliHLTMUONUtils::HeaderOk(
1012                 const AliHLTMUONSinglesDecisionBlockStruct& block,
1013                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
1014         )
1015 {
1016         /// Method used to check if the header information corresponds to the
1017         /// supposed type of the raw dHLT data block.
1018         /// [in]  \param block  The data block to check.
1019         /// [out] \param reason  If this is not NULL, then it is assumed to point
1020         ///      to an array of at least 'reasonCount' number of elements. It will
1021         ///      be filled with the reason codes describing why the header is not
1022         ///      valid.
1023         /// [in/out] \param reasonCount  This should initially specify the size of
1024         ///      the array pointed to by 'reason'. It will be filled with the number
1025         ///      of items actually filled into the reason array upon exit from this
1026         ///      method.
1027         /// \returns  true if there is no problem with the header and false otherwise.
1028         
1029         AliHLTUInt32_t maxCount = reasonCount;
1030         reasonCount = 0;
1031         bool result = true;
1032         
1033         // The block must have the correct type.
1034         if (block.fHeader.fType != kSinglesDecisionDataBlock)
1035         {
1036                 if (reason != NULL and reasonCount < maxCount)
1037                 {
1038                         reason[reasonCount] = kHeaderContainsWrongType;
1039                         reasonCount++;
1040                 }
1041                 result = false;
1042         }
1043         
1044         // The block's record width must be the correct size.
1045         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONTrackDecisionStruct))
1046         {
1047                 if (reason != NULL and reasonCount < maxCount)
1048                 {
1049                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
1050                         reasonCount++;
1051                 }
1052                 result = false;
1053         }
1054         
1055         return result;
1056 }
1057
1058
1059 bool AliHLTMUONUtils::HeaderOk(
1060                 const AliHLTMUONPairsDecisionBlockStruct& block,
1061                 WhyNotValid* reason, AliHLTUInt32_t& reasonCount
1062         )
1063 {
1064         /// Method used to check if the header information corresponds to the
1065         /// supposed type of the raw dHLT data block.
1066         /// [in]  \param block  The data block to check.
1067         /// [out] \param reason  If this is not NULL, then it is assumed to point
1068         ///      to an array of at least 'reasonCount' number of elements. It will
1069         ///      be filled with the reason codes describing why the header is not
1070         ///      valid.
1071         /// [in/out] \param reasonCount  This should initially specify the size of
1072         ///      the array pointed to by 'reason'. It will be filled with the number
1073         ///      of items actually filled into the reason array upon exit from this
1074         ///      method.
1075         /// \returns  true if there is no problem with the header and false otherwise.
1076         
1077         AliHLTUInt32_t maxCount = reasonCount;
1078         reasonCount = 0;
1079         bool result = true;
1080         
1081         // The block must have the correct type.
1082         if (block.fHeader.fType != kPairsDecisionDataBlock)
1083         {
1084                 if (reason != NULL and reasonCount < maxCount)
1085                 {
1086                         reason[reasonCount] = kHeaderContainsWrongType;
1087                         reasonCount++;
1088                 }
1089                 result = false;
1090         }
1091         
1092         // The block's record width must be the correct size.
1093         if (block.fHeader.fRecordWidth != sizeof(AliHLTMUONPairDecisionStruct))
1094         {
1095                 if (reason != NULL and reasonCount < maxCount)
1096                 {
1097                         reason[reasonCount] = kHeaderContainsWrongRecordWidth;
1098                         reasonCount++;
1099                 }
1100                 result = false;
1101         }
1102         
1103         return result;
1104 }
1105
1106
1107 bool AliHLTMUONUtils::IntegrityOk(
1108                 const AliHLTMUONTriggerRecordStruct& tr,
1109                 WhyNotValid* reason,
1110                 AliHLTUInt32_t& reasonCount
1111         )
1112 {
1113         /// This method is used to check more extensively if the integrity of the
1114         /// trigger record structure is OK and returns true in that case.
1115         /// [in] \param tr  The trigger record structure to check.
1116         /// [out] \param reason  If this is not NULL, then it is assumed to point
1117         ///      to an array of at least 'reasonCount' number of elements. It will
1118         ///      be filled with the reason codes describing why the structure is
1119         ///      not valid.
1120         /// [in/out] \param reasonCount  This should initially specify the size of
1121         ///      the array pointed to by 'reason'. It will be filled with the number
1122         ///      of items actually filled into the reason array upon exit from this
1123         ///      method.
1124         /// \returns  true if there is no problem with the structure and false otherwise.
1125         
1126         AliHLTUInt32_t maxCount = reasonCount;
1127         reasonCount = 0;
1128         bool result = true;
1129         
1130         // Check that the ID has a valid value.
1131         if (not (tr.fId >= 0 or tr.fId == -1))
1132         {
1133                 if (reason != NULL and reasonCount < maxCount)
1134                 {
1135                         reason[reasonCount] = kInvalidIdValue;
1136                         reasonCount++;
1137                 }
1138                 result = false;
1139         }
1140         
1141         // Make sure that the reserved bits in the fFlags field are set
1142         // to zero.
1143         if ((tr.fFlags & 0x3FFFFFF0) != 0)
1144         {
1145                 if (reason != NULL and reasonCount < maxCount)
1146                 {
1147                         reason[reasonCount] = kReservedBitsNotZero;
1148                         reasonCount++;
1149                 }
1150                 result = false;
1151         }
1152
1153         // Make sure the sign is not invalid.
1154         if ((tr.fFlags & 0xC0000000) == 0xC0000000)
1155         {
1156                 if (reason != NULL and reasonCount < maxCount)
1157                 {
1158                         reason[reasonCount] = kParticleSignBitsNotValid;
1159                         reasonCount++;
1160                 }
1161                 result = false;
1162         }
1163
1164         // Check that fHit[i] is nil if the corresponding bit in the
1165         // flags word is zero.
1166         const AliHLTMUONRecHitStruct& nilhit
1167                 = AliHLTMUONConstants::NilRecHitStruct();
1168         if ( ((tr.fFlags & 0x1) == 0 and tr.fHit[0] != nilhit) or
1169              ((tr.fFlags & 0x2) == 0 and tr.fHit[1] != nilhit) or
1170              ((tr.fFlags & 0x4) == 0 and tr.fHit[2] != nilhit) or
1171              ((tr.fFlags & 0x8) == 0 and tr.fHit[3] != nilhit)
1172            )
1173         {
1174                 if (reason != NULL and reasonCount < maxCount)
1175                 {
1176                         reason[reasonCount] = kHitNotMarkedAsNil;
1177                         reasonCount++;
1178                 }
1179                 result = false;
1180         }
1181
1182         return result;
1183 }
1184
1185
1186 bool AliHLTMUONUtils::IntegrityOk(
1187                 const AliHLTMUONTriggerRecordsBlockStruct& block,
1188                 WhyNotValid* reason,
1189                 AliHLTUInt32_t* recordNum,
1190                 AliHLTUInt32_t& reasonCount
1191         )
1192 {
1193         /// This method is used to check more extensively if the integrity of the
1194         /// dHLT raw internal data block is OK and returns true in that case.
1195         /// [in] \param block  The trigger record data block to check.
1196         /// [out] \param reason  If this is not NULL, then it is assumed to point
1197         ///      to an array of at least 'reasonCount' number of elements. It will
1198         ///      be filled with the reason codes describing why the data block is
1199         ///      not valid.
1200         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1201         ///      to an array of at least 'reasonCount' number of elements. It will
1202         ///      be filled with the number of the trigger record that had a problem.
1203         ///      The value 'recordNum[i]' will only contain a valid value if
1204         ///      the corresponding 'reason[i]' contains one of:
1205         ///        - kInvalidIdValue
1206         ///        - kReservedBitsNotZero
1207         ///        - kParticleSignBitsNotValid
1208         ///        - kHitNotMarkedAsNil
1209         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1210         ///      was set and is valid or not.
1211         /// [in/out] \param reasonCount  This should initially specify the size of
1212         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1213         ///      with the number of items actually filled into the arrays upon exit
1214         ///      from this method.
1215         /// \returns  true if there is no problem with the data and false otherwise.
1216         
1217         AliHLTUInt32_t maxCount = reasonCount;
1218         bool result = HeaderOk(block, reason, reasonCount);
1219         
1220         const AliHLTMUONTriggerRecordStruct* triggerRecord =
1221                 reinterpret_cast<const AliHLTMUONTriggerRecordStruct*>(&block + 1);
1222
1223         // Check if any ID is duplicated.
1224         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1225         {
1226                 AliHLTInt32_t id = triggerRecord[i].fId;
1227                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1228                 {
1229                         if (id == triggerRecord[j].fId)
1230                         {
1231                                 if (reason != NULL and reasonCount < maxCount)
1232                                 {
1233                                         reason[reasonCount] = kFoundDuplicateIDs;
1234                                         reasonCount++;
1235                                 }
1236                                 result = false;
1237                         }
1238                 }
1239         }
1240
1241         // Check integrity of individual trigger records.
1242         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1243         {
1244                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1245                 if (not IntegrityOk(triggerRecord[i], reason+reasonCount, filledCount))
1246                 {
1247                         // reasons filled in IntegrityOk, now we just need to adjust
1248                         // reasonCount and fill the recordNum values.
1249                         if (recordNum != NULL)
1250                         {
1251                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1252                                         recordNum[reasonCount + n] = i;
1253                         }
1254                         reasonCount += filledCount;
1255                         result = false;
1256                 }
1257         }
1258
1259         return result;
1260 }
1261
1262
1263 bool AliHLTMUONUtils::IntegrityOk(
1264                 const AliHLTMUONTrigRecInfoStruct& trigInfo,
1265                 WhyNotValid* reason,
1266                 AliHLTUInt32_t& reasonCount
1267         )
1268 {
1269         /// This method is used to check more extensively if the integrity of the
1270         /// trigger record debug information structure is OK and returns true in that case.
1271         /// [in] \param trigInfo  The trigger record debug information structure to check.
1272         /// [out] \param reason  If this is not NULL, then it is assumed to point
1273         ///      to an array of at least 'reasonCount' number of elements. It will
1274         ///      be filled with the reason codes describing why the structure is not
1275         ///      valid.
1276         /// [in/out] \param reasonCount  This should initially specify the size of
1277         ///      the array pointed to by 'reason'. It will be filled with the number
1278         ///      of items actually filled into the reason array upon exit from this
1279         ///      method.
1280         /// \returns  true if there is no problem with the structure and false otherwise.
1281         
1282         AliHLTUInt32_t maxCount = reasonCount;
1283         reasonCount = 0;
1284         bool result = true;
1285         
1286         // Check that the trigger ID has a valid value.
1287         if (not (trigInfo.fTrigRecId >= 0 or trigInfo.fTrigRecId == -1))
1288         {
1289                 if (reason != NULL and reasonCount < maxCount)
1290                 {
1291                         reason[reasonCount] = kInvalidIdValue;
1292                         reasonCount++;
1293                 }
1294                 result = false;
1295         }
1296
1297         // Check that the fDetElemId[i] numbers are valid.
1298         if ( not (trigInfo.fDetElemId[0] >= 0 or trigInfo.fDetElemId[0] == -1) or
1299              not (trigInfo.fDetElemId[1] >= 0 or trigInfo.fDetElemId[1] == -1) or
1300              not (trigInfo.fDetElemId[2] >= 0 or trigInfo.fDetElemId[2] == -1) or
1301              not (trigInfo.fDetElemId[3] >= 0 or trigInfo.fDetElemId[3] == -1)
1302            )
1303         {
1304                 if (reason != NULL and reasonCount < maxCount)
1305                 {
1306                         reason[reasonCount] = kInvalidDetElementNumber;
1307                         reasonCount++;
1308                 }
1309                 result = false;
1310         }
1311
1312         return result;
1313 }
1314
1315
1316 bool AliHLTMUONUtils::IntegrityOk(
1317                 const AliHLTMUONTrigRecsDebugBlockStruct& block,
1318                 WhyNotValid* reason,
1319                 AliHLTUInt32_t* recordNum,
1320                 AliHLTUInt32_t& reasonCount
1321         )
1322 {
1323         /// This method is used to check more extensively if the integrity of the
1324         /// dHLT raw internal data block is OK and returns true in that case.
1325         /// [in] \param block  The trigger record debugging information data block
1326         ///      to check.
1327         /// [out] \param reason  If this is not NULL, then it is assumed to point
1328         ///      to an array of at least 'reasonCount' number of elements. It will
1329         ///      be filled with the reason codes describing why the data block is
1330         ///      not valid.
1331         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1332         ///      to an array of at least 'reasonCount' number of elements. It will
1333         ///      be filled with the number of the trigger record debug information
1334         ///      structure that had a problem.
1335         ///      The value 'recordNum[i]' will only contain a valid value if
1336         ///      the corresponding 'reason[i]' contains one of:
1337         ///        - kInvalidIdValue
1338         ///        - kInvalidDetElementNumber
1339         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1340         ///      was set and is valid or not.
1341         /// [in/out] \param reasonCount  This should initially specify the size of
1342         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1343         ///      with the number of items actually filled into the arrays upon exit
1344         ///      from this method.
1345         /// \returns  true if there is no problem with the data and false otherwise.
1346         
1347         AliHLTUInt32_t maxCount = reasonCount;
1348         bool result = HeaderOk(block, reason, reasonCount);
1349         
1350         const AliHLTMUONTrigRecInfoStruct* triggerInfo =
1351                 reinterpret_cast<const AliHLTMUONTrigRecInfoStruct*>(&block + 1);
1352
1353         // Check if any trigger debug info structure has duplicated trigger IDs.
1354         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1355         {
1356                 AliHLTInt32_t id = triggerInfo[i].fTrigRecId;
1357                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1358                 {
1359                         if (id == triggerInfo[j].fTrigRecId)
1360                         {
1361                                 if (reason != NULL and reasonCount < maxCount)
1362                                 {
1363                                         reason[reasonCount] = kFoundDuplicateIDs;
1364                                         reasonCount++;
1365                                 }
1366                                 result = false;
1367                         }
1368                 }
1369         }
1370
1371         // Check integrity of individual trigger records.
1372         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1373         {
1374                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1375                 if (not IntegrityOk(triggerInfo[i], reason+reasonCount, filledCount))
1376                 {
1377                         // reasons filled in IntegrityOk, now we just need to adjust
1378                         // reasonCount and fill the recordNum values.
1379                         if (recordNum != NULL)
1380                         {
1381                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1382                                         recordNum[reasonCount + n] = i;
1383                         }
1384                         reasonCount += filledCount;
1385                         result = false;
1386                 }
1387         }
1388         
1389         return result;
1390 }
1391
1392
1393 bool AliHLTMUONUtils::IntegrityOk(
1394                 const AliHLTMUONTriggerChannelsBlockStruct& block,
1395                 WhyNotValid* reason
1396         )
1397 {
1398         /// This method is used to check more extensively if the integrity of the
1399         /// dHLT raw internal data block is OK and returns true in that case.
1400         /// [in] \param block  The trigger channels data block to check.
1401         /// [out] \param reason  If this is not NULL, then it will be filled with
1402         ///      the reason code describing why the data block is not valid, if and
1403         ///      only if a problem is found with the data.
1404         /// \returns  true if there is no problem with the data and false otherwise.
1405         
1406         if (not HeaderOk(block, reason)) return false;
1407         return true;
1408 }
1409
1410
1411 bool AliHLTMUONUtils::IntegrityOk(
1412                 const AliHLTMUONRecHitsBlockStruct& block,
1413                 WhyNotValid* reason,
1414                 AliHLTUInt32_t& reasonCount
1415         )
1416 {
1417         /// This method is used to check more extensively if the integrity of the
1418         /// dHLT raw internal data block is OK and returns true in that case.
1419         /// [in] \param block  The reconstructed hits data block to check.
1420         /// [out] \param reason  If this is not NULL, then it is assumed to point
1421         ///      to an array of at least 'reasonCount' number of elements. It will
1422         ///      be filled with the reason codes describing why the data block is
1423         ///      not valid.
1424         /// [in/out] \param reasonCount  This should initially specify the size of
1425         ///      the array pointed to by 'reason'. It will be filled with the number
1426         ///      of items actually filled into the reason array upon exit from this
1427         ///      method.
1428         /// \returns  true if there is no problem with the data and false otherwise.
1429         
1430         AliHLTUInt32_t maxCount = reasonCount;
1431         bool result = HeaderOk(block, reason, reasonCount);
1432         
1433         const AliHLTMUONRecHitStruct* hit =
1434                 reinterpret_cast<const AliHLTMUONRecHitStruct*>(&block + 1);
1435
1436         // Check if any hit structure has been duplicated.
1437         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1438         {
1439                 const AliHLTMUONRecHitStruct& h = hit[i];
1440                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1441                 {
1442                         if (h == hit[j])
1443                         {
1444                                 if (reason != NULL and reasonCount < maxCount)
1445                                 {
1446                                         reason[reasonCount] = kFoundDuplicateHits;
1447                                         reasonCount++;
1448                                 }
1449                                 result = false;
1450                         }
1451                 }
1452         }
1453         
1454         return result;
1455 }
1456
1457
1458 bool AliHLTMUONUtils::IntegrityOk(
1459                 const AliHLTMUONClusterStruct& cluster,
1460                 WhyNotValid* reason,
1461                 AliHLTUInt32_t& reasonCount
1462         )
1463 {
1464         /// This method is used to check more extensively if the integrity of the
1465         /// cluster structure is OK and returns true in that case.
1466         /// [in] \param cluster  The cluster structure to check.
1467         /// [out] \param reason  If this is not NULL, then it is assumed to point
1468         ///      to an array of at least 'reasonCount' number of elements. It will
1469         ///      be filled with the reason codes describing why the structure is
1470         ///      not valid.
1471         /// [in/out] \param reasonCount  This should initially specify the size of
1472         ///      the array pointed to by 'reason'. It will be filled with the number
1473         ///      of items actually filled into the reason array upon exit from this
1474         ///      method.
1475         /// \returns  true if there is no problem with the structure and false otherwise.
1476         
1477         AliHLTUInt32_t maxCount = reasonCount;
1478         reasonCount = 0;
1479         bool result = true;
1480         
1481         // Check that the cluster ID has a valid value.
1482         if (not (cluster.fId >= 0 or cluster.fId == -1))
1483         {
1484                 if (reason != NULL and reasonCount < maxCount)
1485                 {
1486                         reason[reasonCount] = kInvalidIdValue;
1487                         reasonCount++;
1488                 }
1489                 result = false;
1490         }
1491         
1492         // Check that the cluster does not have a nil value for its hit.
1493         if (cluster.fHit == AliHLTMUONConstants::NilRecHitStruct())
1494         {
1495                 if (reason != NULL and reasonCount < maxCount)
1496                 {
1497                         reason[reasonCount] = kHitIsNil;
1498                         reasonCount++;
1499                 }
1500                 result = false;
1501         }
1502         
1503         // Make sure the detector element is a valid value.
1504         if (not (cluster.fDetElemId >= 0 or cluster.fDetElemId == -1))
1505         {
1506                 if (reason != NULL and reasonCount < maxCount)
1507                 {
1508                         reason[reasonCount] = kInvalidDetElementNumber;
1509                         reasonCount++;
1510                 }
1511                 result = false;
1512         }
1513         
1514         // The number of channels should be in a reasonable range.
1515         // between 1 and the maximum number of channels per DDL.
1516         // 1<<17 taken from the 11 bits MANU ID + 6 bits channel address.
1517         if (cluster.fNchannels < 1 or (1<<17) < cluster.fNchannels)
1518         {
1519                 if (reason != NULL and reasonCount < maxCount)
1520                 {
1521                         reason[reasonCount] = kInvalidChannelCount;
1522                         reasonCount++;
1523                 }
1524                 result = false;
1525         }
1526
1527         return result;
1528 }
1529
1530
1531 bool AliHLTMUONUtils::IntegrityOk(
1532                 const AliHLTMUONClustersBlockStruct& block,
1533                 WhyNotValid* reason,
1534                 AliHLTUInt32_t* recordNum,
1535                 AliHLTUInt32_t& reasonCount
1536         )
1537 {
1538         /// This method is used to check more extensively if the integrity of the
1539         /// dHLT internal clusters data block is OK and returns true in that case.
1540         /// [in] \param block  The clusters data block to check.
1541         /// [out] \param reason  If this is not NULL, then it is assumed to point
1542         ///      to an array of at least 'reasonCount' number of elements. It will
1543         ///      be filled with the reason codes describing why the data block is
1544         ///      not valid.
1545         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1546         ///      to an array of at least 'reasonCount' number of elements. It will
1547         ///      be filled with the number of the cluster structure that had a problem.
1548         ///      The value 'recordNum[i]' will only contain a valid value if
1549         ///      the corresponding 'reason[i]' contains one of:
1550         ///        - kInvalidIdValue
1551         ///        - kHitIsNil
1552         ///        - kInvalidDetElementNumber
1553         ///        - kInvalidChannelCount
1554         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1555         ///      was set and is valid or not.
1556         /// [in/out] \param reasonCount  This should initially specify the size of
1557         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1558         ///      with the number of items actually filled into the arrays upon exit
1559         ///      from this method.
1560         /// \returns  true if there is no problem with the data and false otherwise.
1561         
1562         AliHLTUInt32_t maxCount = reasonCount;
1563         bool result = HeaderOk(block, reason, reasonCount);
1564
1565         const AliHLTMUONClusterStruct* cluster =
1566                 reinterpret_cast<const AliHLTMUONClusterStruct*>(&block + 1);
1567         
1568         // Check if any ID is duplicated.
1569         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1570         {
1571                 AliHLTInt32_t id = cluster[i].fId;
1572                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1573                 {
1574                         if (id == cluster[j].fId)
1575                         {
1576                                 if (reason != NULL and reasonCount < maxCount)
1577                                 {
1578                                         reason[reasonCount] = kFoundDuplicateIDs;
1579                                         reasonCount++;
1580                                 }
1581                                 result = false;
1582                         }
1583                 }
1584         }
1585
1586         // Check if any hit structure has been duplicated.
1587         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1588         {
1589                 const AliHLTMUONRecHitStruct& h = cluster[i].fHit;
1590                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1591                 {
1592                         if (h == cluster[j].fHit)
1593                         {
1594                                 if (reason != NULL and reasonCount < maxCount)
1595                                 {
1596                                         reason[reasonCount] = kFoundDuplicateHits;
1597                                         reasonCount++;
1598                                 }
1599                                 result = false;
1600                         }
1601                 }
1602         }
1603
1604         // Check integrity of individual cluster structures.
1605         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1606         {
1607                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1608                 if (not IntegrityOk(cluster[i], reason+reasonCount, filledCount))
1609                 {
1610                         // reasons filled in IntegrityOk, now we just need to adjust
1611                         // reasonCount and fill the recordNum values.
1612                         if (recordNum != NULL)
1613                         {
1614                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1615                                         recordNum[reasonCount + n] = i;
1616                         }
1617                         reasonCount += filledCount;
1618                         result = false;
1619                 }
1620         }
1621         
1622         return result;
1623 }
1624
1625
1626 bool AliHLTMUONUtils::IntegrityOk(
1627                 const AliHLTMUONChannelStruct& channel,
1628                 WhyNotValid* reason,
1629                 AliHLTUInt32_t& reasonCount
1630         )
1631 {
1632         /// This method is used to check more extensively if the integrity of the
1633         /// channel structure is OK and returns true in that case.
1634         /// [in] \param cluster  The channel structure to check.
1635         /// [out] \param reason  If this is not NULL, then it is assumed to point
1636         ///      to an array of at least 'reasonCount' number of elements. It will
1637         ///      be filled with the reason codes describing why the structure is
1638         ///      not valid.
1639         /// [in/out] \param reasonCount  This should initially specify the size of
1640         ///      the array pointed to by 'reason'. It will be filled with the number
1641         ///      of items actually filled into the reason array upon exit from this
1642         ///      method.
1643         /// \returns  true if there is no problem with the structure and false otherwise.
1644         
1645         AliHLTUInt32_t maxCount = reasonCount;
1646         reasonCount = 0;
1647         bool result = true;
1648         
1649         // Check that the channel ID has a valid value.
1650         if (not (channel.fClusterId >= 0 or channel.fClusterId == -1))
1651         {
1652                 if (reason != NULL and reasonCount < maxCount)
1653                 {
1654                         reason[reasonCount] = kInvalidIdValue;
1655                         reasonCount++;
1656                 }
1657                 result = false;
1658         }
1659         
1660         // Check that the bus patch ID has a valid value, which fits into 12 bits.
1661         if ((channel.fBusPatch & (~0xFFF)) != 0)
1662         {
1663                 if (reason != NULL and reasonCount < maxCount)
1664                 {
1665                         reason[reasonCount] = kInvalidBusPatchId;
1666                         reasonCount++;
1667                 }
1668                 result = false;
1669         }
1670         
1671         // Check that the MANU ID has a valid value, which fits into 11 bits.
1672         if ((channel.fManu & (~0x7FF)) != 0)
1673         {
1674                 if (reason != NULL and reasonCount < maxCount)
1675                 {
1676                         reason[reasonCount] = kInvalidManuId;
1677                         reasonCount++;
1678                 }
1679                 result = false;
1680         }
1681         
1682         // Check that the channel address has a valid value, which fits into 6 bits.
1683         if ((channel.fChannelAddress & (~0x3F)) != 0)
1684         {
1685                 if (reason != NULL and reasonCount < maxCount)
1686                 {
1687                         reason[reasonCount] = kInvalidChannelAddress;
1688                         reasonCount++;
1689                 }
1690                 result = false;
1691         }
1692         
1693         // Check that the ADC signal has a valid value, which fits into 12 bits.
1694         if ((channel.fSignal & (~0xFFF)) != 0)
1695         {
1696                 if (reason != NULL and reasonCount < maxCount)
1697                 {
1698                         reason[reasonCount] = kInvalidSignal;
1699                         reasonCount++;
1700                 }
1701                 result = false;
1702         }
1703         
1704         // Check that the raw data word corresponds to the unpacked values for
1705         // the ADC signal, MANU ID and channel address.
1706         UShort_t manuId; UChar_t channelId; UShort_t adc;
1707         AliMUONTrackerDDLDecoderEventHandler::UnpackADC(
1708                         channel.fRawDataWord, manuId, channelId, adc
1709                 );
1710         if (manuId != channel.fManu or channelId != channel.fChannelAddress
1711             or adc != channel.fSignal
1712            )
1713         {
1714                 if (reason != NULL and reasonCount < maxCount)
1715                 {
1716                         reason[reasonCount] = kDataWordDifferent;
1717                         reasonCount++;
1718                 }
1719                 result = false;
1720         }
1721
1722         return result;
1723 }
1724
1725
1726 bool AliHLTMUONUtils::IntegrityOk(
1727                 const AliHLTMUONChannelsBlockStruct& block,
1728                 WhyNotValid* reason,
1729                 AliHLTUInt32_t* recordNum,
1730                 AliHLTUInt32_t& reasonCount
1731         )
1732 {
1733         /// This method is used to check more extensively if the integrity of the
1734         /// dHLT internal channels data block is OK and returns true in that case.
1735         /// [in] \param block  The channels data block to check.
1736         /// [out] \param reason  If this is not NULL, then it is assumed to point
1737         ///      to an array of at least 'reasonCount' number of elements. It will
1738         ///      be filled with the reason codes describing why the data block is
1739         ///      not valid.
1740         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1741         ///      to an array of at least 'reasonCount' number of elements. It will
1742         ///      be filled with the number of the channel structure that had a problem.
1743         ///      The value 'recordNum[i]' will only contain a valid value if
1744         ///      the corresponding 'reason[i]' contains one of:
1745         ///        - kInvalidIdValue
1746         ///        - kInvalidBusPatchId
1747         ///        - kInvalidManuId
1748         ///        - kInvalidChannelAddress
1749         ///        - kInvalidSignal
1750         ///        - kDataWordDifferent
1751         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1752         ///      was set and is valid or not.
1753         /// [in/out] \param reasonCount  This should initially specify the size of
1754         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1755         ///      with the number of items actually filled into the arrays upon exit
1756         ///      from this method.
1757         /// \returns  true if there is no problem with the data and false otherwise.
1758         
1759         AliHLTUInt32_t maxCount = reasonCount;
1760         bool result = HeaderOk(block, reason, reasonCount);
1761         
1762         const AliHLTMUONChannelStruct* channel =
1763                 reinterpret_cast<const AliHLTMUONChannelStruct*>(&block + 1);
1764         
1765         // Check if any cluster ID is duplicated.
1766         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1767         {
1768                 AliHLTInt32_t id = channel[i].fClusterId;
1769                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1770                 {
1771                         if (id == channel[j].fClusterId)
1772                         {
1773                                 if (reason != NULL and reasonCount < maxCount)
1774                                 {
1775                                         reason[reasonCount] = kFoundDuplicateIDs;
1776                                         reasonCount++;
1777                                 }
1778                                 result = false;
1779                         }
1780                 }
1781         }
1782
1783         // Check integrity of individual channel structures.
1784         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1785         {
1786                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1787                 if (not IntegrityOk(channel[i], reason+reasonCount, filledCount))
1788                 {
1789                         // reasons filled in IntegrityOk, now we just need to adjust
1790                         // reasonCount and fill the recordNum values.
1791                         if (recordNum != NULL)
1792                         {
1793                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1794                                         recordNum[reasonCount + n] = i;
1795                         }
1796                         reasonCount += filledCount;
1797                         result = false;
1798                 }
1799         }
1800         
1801         return result;
1802 }
1803
1804
1805 bool AliHLTMUONUtils::IntegrityOk(
1806                 const AliHLTMUONMansoTrackStruct& track,
1807                 WhyNotValid* reason,
1808                 AliHLTUInt32_t& reasonCount
1809         )
1810 {
1811         /// This method is used to check more extensively if the integrity of the
1812         /// Manso track structure is OK and returns true in that case.
1813         /// [in] \param track  The track structure to check.
1814         /// [out] \param reason  If this is not NULL, then it is assumed to point
1815         ///      to an array of at least 'reasonCount' number of elements. It will
1816         ///      be filled with the reason codes describing why the structure is
1817         ///      not valid.
1818         /// [in/out] \param reasonCount  This should initially specify the size of
1819         ///      the array pointed to by 'reason'. It will be filled with the number
1820         ///      of items actually filled into the reason array upon exit from this
1821         ///      method.
1822         /// \returns  true if there is no problem with the structure and false otherwise.
1823         
1824         AliHLTUInt32_t maxCount = reasonCount;
1825         reasonCount = 0;
1826         bool result = true;
1827         
1828         // Check that the Manso track ID has a valid value.
1829         if (not (track.fId >= 0 or track.fId == -1))
1830         {
1831                 if (reason != NULL and reasonCount < maxCount)
1832                 {
1833                         reason[reasonCount] = kInvalidIdValue;
1834                         reasonCount++;
1835                 }
1836                 result = false;
1837         }
1838         
1839         // Check that the corresponding trigger record ID has a valid value.
1840         if (not (track.fTrigRec >= 0 or track.fTrigRec == -1))
1841         {
1842                 if (reason != NULL and reasonCount < maxCount)
1843                 {
1844                         reason[reasonCount] = kInvalidTriggerIdValue;
1845                         reasonCount++;
1846                 }
1847                 result = false;
1848         }
1849         
1850         // Make sure that the reserved bits in the fFlags field are set
1851         // to zero.
1852         if ((track.fFlags & 0x3FFFFFF0) != 0)
1853         {
1854                 if (reason != NULL and reasonCount < maxCount)
1855                 {
1856                         reason[reasonCount] = kReservedBitsNotZero;
1857                         reasonCount++;
1858                 }
1859                 result = false;
1860         }
1861
1862         // Make sure the sign is not invalid.
1863         if ((track.fFlags & 0xC0000000) == 0xC0000000)
1864         {
1865                 if (reason != NULL and reasonCount < maxCount)
1866                 {
1867                         reason[reasonCount] = kParticleSignBitsNotValid;
1868                         reasonCount++;
1869                 }
1870                 result = false;
1871         }
1872
1873         // Check that fHit[i] is nil if the corresponding bit in the
1874         // flags word is zero.
1875         const AliHLTMUONRecHitStruct& nilhit
1876                 = AliHLTMUONConstants::NilRecHitStruct();
1877         if ( ((track.fFlags & 0x1) == 0 and track.fHit[0] != nilhit) or
1878              ((track.fFlags & 0x2) == 0 and track.fHit[1] != nilhit) or
1879              ((track.fFlags & 0x4) == 0 and track.fHit[2] != nilhit) or
1880              ((track.fFlags & 0x8) == 0 and track.fHit[3] != nilhit)
1881            )
1882         {
1883                 if (reason != NULL and reasonCount < maxCount)
1884                 {
1885                         reason[reasonCount] = kHitNotMarkedAsNil;
1886                         reasonCount++;
1887                 }
1888                 result = false;
1889         }
1890
1891         // Check that the chi squared value is valid
1892         if (not (track.fChi2 >= 0 or track.fChi2 == -1))
1893         {
1894                 if (reason != NULL and reasonCount < maxCount)
1895                 {
1896                         reason[reasonCount] = kChiSquareInvalid;
1897                         reasonCount++;
1898                 }
1899                 result = false;
1900         }
1901
1902         // Check that if chi squared is -1 then the momentum vector is zero.
1903         if (track.fChi2 == -1 and
1904             not (track.fPx == 0 and track.fPy == 0 and track.fPz == 0)
1905            )
1906         {
1907                 if (reason != NULL and reasonCount < maxCount)
1908                 {
1909                         reason[reasonCount] = kMomentumVectorNotZero;
1910                         reasonCount++;
1911                 }
1912                 result = false;
1913         }
1914         
1915         return result;
1916 }
1917
1918
1919 bool AliHLTMUONUtils::IntegrityOk(
1920                 const AliHLTMUONMansoTracksBlockStruct& block,
1921                 WhyNotValid* reason,
1922                 AliHLTUInt32_t* recordNum,
1923                 AliHLTUInt32_t& reasonCount
1924         )
1925 {
1926         /// This method is used to check more extensively if the integrity of the
1927         /// dHLT internal Manso track data block is OK and returns true in that case.
1928         /// [in] \param block  The Manso track data block to check.
1929         /// [out] \param reason  If this is not NULL, then it is assumed to point
1930         ///      to an array of at least 'reasonCount' number of elements. It will
1931         ///      be filled with the reason codes describing why the data block is
1932         ///      not valid.
1933         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
1934         ///      to an array of at least 'reasonCount' number of elements. It will
1935         ///      be filled with the number of the Manso track that had a problem.
1936         ///      The value 'recordNum[i]' will only contain a valid value if
1937         ///      the corresponding 'reason[i]' contains one of:
1938         ///        - kInvalidIdValue
1939         ///        - kInvalidTriggerIdValue
1940         ///        - kReservedBitsNotZero
1941         ///        - kParticleSignBitsNotValid
1942         ///        - kHitNotMarkedAsNil
1943         ///        - kChiSquareInvalid
1944         ///        - kMomentumVectorNotZero
1945         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
1946         ///      was set and is valid or not.
1947         /// [in/out] \param reasonCount  This should initially specify the size of
1948         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
1949         ///      with the number of items actually filled into the arrays upon exit
1950         ///      from this method.
1951         /// \returns  true if there is no problem with the data and false otherwise.
1952         
1953         AliHLTUInt32_t maxCount = reasonCount;
1954         bool result = HeaderOk(block, reason, reasonCount);
1955         
1956         const AliHLTMUONMansoTrackStruct* track =
1957                 reinterpret_cast<const AliHLTMUONMansoTrackStruct*>(&block + 1);
1958         
1959         // Check if any track ID is duplicated.
1960         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1961         {
1962                 AliHLTInt32_t id = track[i].fId;
1963                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
1964                 {
1965                         if (id == track[j].fId)
1966                         {
1967                                 if (reason != NULL and reasonCount < maxCount)
1968                                 {
1969                                         reason[reasonCount] = kFoundDuplicateIDs;
1970                                         reasonCount++;
1971                                 }
1972                                 result = false;
1973                         }
1974                 }
1975         }
1976         
1977         // Check that all the tracks have integrity.
1978         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
1979         {
1980                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
1981                 if (not IntegrityOk(track[i], reason+reasonCount, filledCount))
1982                 {
1983                         // reasons filled in IntegrityOk, now we just need to adjust
1984                         // reasonCount and fill the recordNum values.
1985                         if (recordNum != NULL)
1986                         {
1987                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
1988                                         recordNum[reasonCount + n] = i;
1989                         }
1990                         reasonCount += filledCount;
1991                         result = false;
1992                 }
1993         }
1994         
1995         return result;
1996 }
1997
1998
1999 bool AliHLTMUONUtils::IntegrityOk(
2000                 const AliHLTMUONMansoCandidateStruct& candidate,
2001                 WhyNotValid* reason,
2002                 AliHLTUInt32_t& reasonCount
2003         )
2004 {
2005         /// This method is used to check more extensively if the integrity of the
2006         /// Manso track candidate structure is OK and returns true in that case.
2007         /// [in] \param track  The track candidate structure to check.
2008         /// [out] \param reason  If this is not NULL, then it is assumed to point
2009         ///      to an array of at least 'reasonCount' number of elements. It will
2010         ///      be filled with the reason codes describing why the structure is
2011         ///      not valid.
2012         /// [in/out] \param reasonCount  This should initially specify the size of
2013         ///      the array pointed to by 'reason'. It will be filled with the number
2014         ///      of items actually filled into the reason array upon exit from this
2015         ///      method.
2016         /// \returns  true if there is no problem with the structure and false otherwise.
2017         
2018         // First check the integrity of the candidate track structure.
2019         AliHLTUInt32_t maxCount = reasonCount;
2020         bool result = IntegrityOk(candidate.fTrack, reason, reasonCount);
2021         
2022         // Now check that the ROIs are reasonable.
2023         // The radius must be positive or -1 indicating computation error and
2024         // the corresponding hit in the track must be within the ROI.
2025         for (AliHLTUInt32_t i = 0; i < 4; i++)
2026         {
2027                 if (not (candidate.fRoI[i].fRadius >= 0 or candidate.fRoI[i].fRadius == -1))
2028                 {
2029                         if (reason != NULL and reasonCount < maxCount)
2030                         {
2031                                 reason[reasonCount] = kRoiRadiusInvalid;
2032                                 reasonCount++;
2033                         }
2034                         result = false;
2035                 }
2036                 
2037                 // Check if the corresponding hit was even found in the track.
2038                 if ( (candidate.fTrack.fFlags & (0x1 << i)) == 0 ) continue;
2039                 
2040                 double dx = candidate.fRoI[i].fX - candidate.fTrack.fHit[i].fX;
2041                 double dy = candidate.fRoI[i].fY - candidate.fTrack.fHit[i].fY;
2042                 double dz = candidate.fRoI[i].fZ - candidate.fTrack.fHit[i].fZ;
2043                 double r = sqrt(dx*dx + dy*dy);
2044                 // Check if the projected distance between ROI centre and hit is
2045                 // bigger than the ROI radius. Also the difference between z
2046                 // coordinates should not exceed 20 cm.
2047                 if (r > candidate.fRoI[i].fRadius or fabs(dz) > 20.)
2048                 {
2049                         if (reason != NULL and reasonCount < maxCount)
2050                         {
2051                                 reason[reasonCount] = kHitNotWithinRoi;
2052                                 reasonCount++;
2053                         }
2054                         result = false;
2055                 }
2056         }
2057         
2058         return result;
2059 }
2060
2061
2062 bool AliHLTMUONUtils::IntegrityOk(
2063                 const AliHLTMUONMansoCandidatesBlockStruct& block,
2064                 WhyNotValid* reason,
2065                 AliHLTUInt32_t* recordNum,
2066                 AliHLTUInt32_t& reasonCount
2067         )
2068 {
2069         /// This method is used to check more extensively if the integrity of the
2070         /// dHLT internal Manso candidates data block is OK and returns true in
2071         /// that case.
2072         /// [in] \param block  The Manso track candidate data block to check.
2073         /// [out] \param reason  If this is not NULL, then it is assumed to point
2074         ///      to an array of at least 'reasonCount' number of elements. It will
2075         ///      be filled with the reason codes describing why the data block is
2076         ///      not valid.
2077         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2078         ///      to an array of at least 'reasonCount' number of elements. It will
2079         ///      be filled with the number of the track candidate that had a problem.
2080         ///      The value 'recordNum[i]' will only contain a valid value if
2081         ///      the corresponding 'reason[i]' contains one of:
2082         ///        - kInvalidIdValue
2083         ///        - kInvalidTriggerIdValue
2084         ///        - kReservedBitsNotZero
2085         ///        - kParticleSignBitsNotValid
2086         ///        - kHitNotMarkedAsNil
2087         ///        - kChiSquareInvalid
2088         ///        - kRoiRadiusInvalid
2089         ///        - kHitNotWithinRoi
2090         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2091         ///      was set and is valid or not.
2092         /// [in/out] \param reasonCount  This should initially specify the size of
2093         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2094         ///      with the number of items actually filled into the arrays upon exit
2095         ///      from this method.
2096         /// \returns  true if there is no problem with the data and false otherwise.
2097         
2098         AliHLTUInt32_t maxCount = reasonCount;
2099         bool result = HeaderOk(block, reason, reasonCount);
2100
2101         const AliHLTMUONMansoCandidateStruct* candidate =
2102                 reinterpret_cast<const AliHLTMUONMansoCandidateStruct*>(&block + 1);
2103         
2104         // Check if any candidate track ID is duplicated.
2105         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2106         {
2107                 AliHLTInt32_t id = candidate[i].fTrack.fId;
2108                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2109                 {
2110                         if (id == candidate[j].fTrack.fId)
2111                         {
2112                                 if (reason != NULL and reasonCount < maxCount)
2113                                 {
2114                                         reason[reasonCount] = kFoundDuplicateIDs;
2115                                         reasonCount++;
2116                                 }
2117                                 result = false;
2118                         }
2119                 }
2120         }
2121         
2122         // Check that all the track candidates have integrity.
2123         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2124         {
2125                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2126                 if (not IntegrityOk(candidate[i], reason+reasonCount, filledCount))
2127                 {
2128                         // reasons filled in IntegrityOk, now we just need to adjust
2129                         // reasonCount and fill the recordNum values.
2130                         if (recordNum != NULL)
2131                         {
2132                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2133                                         recordNum[reasonCount + n] = i;
2134                         }
2135                         reasonCount += filledCount;
2136                         result = false;
2137                 }
2138         }
2139         
2140         return result;
2141 }
2142
2143
2144 bool AliHLTMUONUtils::IntegrityOk(
2145                 const AliHLTMUONTrackDecisionStruct& decision,
2146                 WhyNotValid* reason,
2147                 AliHLTUInt32_t& reasonCount
2148         )
2149 {
2150         /// This method is used to check more extensively if the integrity of the
2151         /// single track trigger decision structure is OK and returns true in that case.
2152         /// [in] \param decision  The trigger decision structure to check.
2153         /// [out] \param reason  If this is not NULL, then it is assumed to point
2154         ///      to an array of at least 'reasonCount' number of elements. It will
2155         ///      be filled with the reason codes describing why the structure is not
2156         ///      valid.
2157         /// [in/out] \param reasonCount  This should initially specify the size of
2158         ///      the array pointed to by 'reason'. It will be filled with the number
2159         ///      of items actually filled into the reason array upon exit from this
2160         ///      method.
2161         /// \returns  true if there is no problem with the structure and false otherwise.
2162         
2163         AliHLTUInt32_t maxCount = reasonCount;
2164         reasonCount = 0;
2165         bool result = true;
2166         
2167         // The track ID value must be positive or -1.
2168         if (not (decision.fTrackId >= 0 or decision.fTrackId == -1))
2169         {
2170                 if (reason != NULL and reasonCount < maxCount)
2171                 {
2172                         reason[reasonCount] = kInvalidTrackIdValue;
2173                         reasonCount++;
2174                 }
2175                 result = false;
2176         }
2177         
2178         // Make sure that the reserved bits in the fTriggerBits field are set
2179         // to zero.
2180         if ((decision.fTriggerBits & 0xFFFFFFFC) != 0)
2181         {
2182                 if (reason != NULL and reasonCount < maxCount)
2183                 {
2184                         reason[reasonCount] = kReservedBitsNotZero;
2185                         reasonCount++;
2186                 }
2187                 result = false;
2188         }
2189         
2190         // The pT should be -1 or a positive number.
2191         if (decision.fPt != -1. and decision.fPt < 0.)
2192         {
2193                 if (reason != NULL and reasonCount < maxCount)
2194                 {
2195                         reason[reasonCount] = kPtValueNotValid;
2196                         reasonCount++;
2197                 }
2198                 result = false;
2199         }
2200         
2201         return result;
2202 }
2203
2204
2205 bool AliHLTMUONUtils::IntegrityOk(
2206                 const AliHLTMUONSinglesDecisionBlockStruct& block,
2207                 WhyNotValid* reason,
2208                 AliHLTUInt32_t* recordNum,
2209                 AliHLTUInt32_t& reasonCount
2210         )
2211 {
2212         /// This method is used to check more extensively if the integrity of the
2213         /// dHLT internal single track trigger decision data block is OK and returns
2214         /// true in that case.
2215         /// [in] \param block  The single track trigger decision data block to check.
2216         /// [out] \param reason  If this is not NULL, then it is assumed to point
2217         ///      to an array of at least 'reasonCount' number of elements. It will
2218         ///      be filled with the reason codes describing why the data block is
2219         ///      not valid.
2220         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2221         ///      to an array of at least 'reasonCount' number of elements. It will
2222         ///      be filled with the number of the trigger decision that had a problem.
2223         ///      The value 'recordNum[i]' will only contain a valid value if
2224         ///      the corresponding 'reason[i]' contains one of:
2225         ///        - kInvalidTrackIdValue
2226         ///        - kReservedBitsNotZero
2227         ///        - kPtValueNotValid
2228         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2229         ///      was set and is valid or not.
2230         /// [in/out] \param reasonCount  This should initially specify the size of
2231         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2232         ///      with the number of items actually filled into the arrays upon exit
2233         ///      from this method.
2234         /// \returns  true if there is no problem with the data and false otherwise.
2235         
2236         AliHLTUInt32_t maxCount = reasonCount;
2237         bool result = HeaderOk(block, reason, reasonCount);
2238         
2239         const AliHLTMUONTrackDecisionStruct* decision =
2240                 reinterpret_cast<const AliHLTMUONTrackDecisionStruct*>(&block + 1);
2241
2242         // Check that there are no duplicate trigger entries.
2243         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2244         {
2245                 AliHLTInt32_t id = decision[i].fTrackId;
2246                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2247                 {
2248                         if (id == decision[j].fTrackId)
2249                         {
2250                                 if (reason != NULL and reasonCount < maxCount)
2251                                 {
2252                                         reason[reasonCount] = kFoundDuplicateTriggers;
2253                                         reasonCount++;
2254                                 }
2255                                 result = false;
2256                         }
2257                 }
2258         }
2259         
2260         // Check that the trigger bits for each track have integrity.
2261         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2262         {
2263                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2264                 if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
2265                 {
2266                         // Reasons filled in IntegrityOk, now we just need to adjust
2267                         // reasonCount and fill the recordNum values.
2268                         if (recordNum != NULL)
2269                         {
2270                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2271                                         recordNum[reasonCount + n] = i;
2272                         }
2273                         reasonCount += filledCount;
2274                         result = false;
2275                 }
2276         }
2277         
2278         return result;
2279 }
2280
2281
2282 bool AliHLTMUONUtils::IntegrityOk(
2283                 const AliHLTMUONPairDecisionStruct& decision,
2284                 WhyNotValid* reason,
2285                 AliHLTUInt32_t& reasonCount
2286         )
2287 {
2288         /// This method is used to check more extensively if the integrity of the
2289         /// track pair trigger decision structure is OK and returns true in that case.
2290         /// [in] \param decision  The trigger decision structure to check.
2291         /// [out] \param reason  If this is not NULL, then it is assumed to point
2292         ///      to an array of at least 'reasonCount' number of elements. It will
2293         ///      be filled with the reason codes describing why the structure is not
2294         ///      valid.
2295         /// [in/out] \param reasonCount  This should initially specify the size of
2296         ///      the array pointed to by 'reason'. It will be filled with the number
2297         ///      of items actually filled into the reason array upon exit from this
2298         ///      method.
2299         /// \returns  true if there is no problem with the structure and false otherwise.
2300         
2301         AliHLTUInt32_t maxCount = reasonCount;
2302         reasonCount = 0;
2303         bool result = true;
2304         
2305         //kInvalidTrackIdValue
2306         
2307         // The track IDs must have a positive value or -1.
2308         if (not (decision.fTrackAId >= 0 or decision.fTrackAId == -1) or
2309             not (decision.fTrackBId >= 0 or decision.fTrackBId == -1)
2310            )
2311         {
2312                 if (reason != NULL and reasonCount < maxCount)
2313                 {
2314                         reason[reasonCount] = kInvalidTrackIdValue;
2315                         reasonCount++;
2316                 }
2317                 result = false;
2318         }
2319         
2320         // Make sure that the reserved bits in the fTriggerBits field are set
2321         // to zero.
2322         if ((decision.fTriggerBits & 0xFFFFFF80) != 0)
2323         {
2324                 if (reason != NULL and reasonCount < maxCount)
2325                 {
2326                         reason[reasonCount] = kReservedBitsNotZero;
2327                         reasonCount++;
2328                 }
2329                 result = false;
2330         }
2331         
2332         // Check that the track IDs are not the same.
2333         if (decision.fTrackAId == decision.fTrackBId)
2334         {
2335                 if (reason != NULL and reasonCount < maxCount)
2336                 {
2337                         reason[reasonCount] = kPairTrackIdsAreIdentical;
2338                         reasonCount++;
2339                 }
2340                 result = false;
2341         }
2342         
2343         // The invariant mass should be -1 or a positive number.
2344         if (decision.fInvMass != -1. and decision.fInvMass < 0.)
2345         {
2346                 if (reason != NULL and reasonCount < maxCount)
2347                 {
2348                         reason[reasonCount] = kMassValueNotValid;
2349                         reasonCount++;
2350                 }
2351                 result = false;
2352         }
2353         
2354         // Neither the high pt (hipt) or low pt (lopt) count bits can be > 2.
2355         AliHLTUInt8_t lowPtCount = (decision.fTriggerBits & 0x00000003);
2356         AliHLTUInt8_t highPtCount = (decision.fTriggerBits & 0x0000000C) >> 2;
2357         if (lowPtCount > 2)
2358         {
2359                 if (reason != NULL and reasonCount < maxCount)
2360                 {
2361                         reason[reasonCount] = kLowPtCountInvalid;
2362                         reasonCount++;
2363                 }
2364                 result = false;
2365         }
2366         if (highPtCount > 2)
2367         {
2368                 if (reason != NULL and reasonCount < maxCount)
2369                 {
2370                         reason[reasonCount] = kHighPtCountInvalid;
2371                         reasonCount++;
2372                 }
2373                 result = false;
2374         }
2375         
2376         return result;
2377 }
2378
2379
2380 bool AliHLTMUONUtils::IntegrityOk(
2381                 const AliHLTMUONPairsDecisionBlockStruct& block,
2382                 WhyNotValid* reason,
2383                 AliHLTUInt32_t* recordNum,
2384                 AliHLTUInt32_t& reasonCount
2385         )
2386 {
2387         /// This method is used to check more extensively if the integrity of the
2388         /// dHLT internal track pair trigger decision data block is OK and returns
2389         /// true in that case.
2390         /// [in] \param block  The track pair trigger decision data block to check.
2391         /// [out] \param reason  If this is not NULL, then it is assumed to point
2392         ///      to an array of at least 'reasonCount' number of elements. It will
2393         ///      be filled with the reason codes describing why the data block is
2394         ///      not valid.
2395         /// [out] \param recordNum  If this is not NULL, then it is assumed to point
2396         ///      to an array of at least 'reasonCount' number of elements. It will
2397         ///      be filled with the number of the trigger decision that had a problem.
2398         ///      The value 'recordNum[i]' will only contain a valid value if
2399         ///      the corresponding 'reason[i]' contains one of:
2400         ///        - kInvalidTrackIdValue
2401         ///        - kReservedBitsNotZero
2402         ///        - kPairTrackIdsAreIdentical
2403         ///        - kMassValueNotValid
2404         ///        - kLowPtCountInvalid
2405         ///        - kHighPtCountInvalid
2406         /// \note You can use RecordNumberWasSet(reason[i]) to check if 'recordNum[i]'
2407         ///      was set and is valid or not.
2408         /// [in/out] \param reasonCount  This should initially specify the size of
2409         ///      the array pointed to by 'reason' and 'recordNum'. It will be filled
2410         ///      with the number of items actually filled into the arrays upon exit
2411         ///      from this method.
2412         /// \returns  true if there is no problem with the data and false otherwise.
2413         
2414         AliHLTUInt32_t maxCount = reasonCount;
2415         bool result = HeaderOk(block, reason, reasonCount);
2416
2417         const AliHLTMUONPairDecisionStruct* decision =
2418                 reinterpret_cast<const AliHLTMUONPairDecisionStruct*>(&block + 1);
2419         
2420         // Check that there are no duplicate trigger entries.
2421         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2422         {
2423                 AliHLTInt32_t ta = decision[i].fTrackAId;
2424                 AliHLTInt32_t tb = decision[i].fTrackBId;
2425                 for (AliHLTUInt32_t j = i+1; j < block.fHeader.fNrecords; j++)
2426                 {
2427                         if (ta == decision[j].fTrackAId and tb == decision[j].fTrackBId)
2428                         {
2429                                 if (reason != NULL and reasonCount < maxCount)
2430                                 {
2431                                         reason[reasonCount] = kFoundDuplicateTriggers;
2432                                         reasonCount++;
2433                                 }
2434                                 result = false;
2435                         }
2436                 }
2437         }
2438         
2439         // Check that the trigger bits for each track pair have integrity.
2440         for (AliHLTUInt32_t i = 0; i < block.fHeader.fNrecords; i++)
2441         {
2442                 AliHLTUInt32_t filledCount = maxCount - reasonCount;
2443                 if (not IntegrityOk(decision[i], reason+reasonCount, filledCount))
2444                 {
2445                         // Reasons filled in IntegrityOk, now we just need to adjust
2446                         // reasonCount and fill the recordNum values.
2447                         if (recordNum != NULL)
2448                         {
2449                                 for (AliHLTUInt32_t n = 0; n < filledCount; n++)
2450                                         recordNum[reasonCount + n] = i;
2451                         }
2452                         reasonCount += filledCount;
2453                         result = false;
2454                 }
2455         }
2456         
2457         return result;
2458 }
2459