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