a18e37a491d7989003de2ece6840a2f85168da36
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONDecisionComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id: $ */
18
19 ///
20 ///  @file   AliHLTMUONDecisionComponent.cxx
21 ///  @author Artur Szostak <artursz@iafrica.com>
22 ///  @date   30 April 2008
23 ///  @brief  Implementation of the decision component for dimuon HLT triggering.
24 ///
25 // class documentation is in the header file.
26
27 #include "AliHLTMUONDecisionComponent.h"
28 #include "AliHLTMUONConstants.h"
29 #include "AliHLTMUONUtils.h"
30 #include "AliHLTMUONCalculations.h"
31 #include "AliHLTMUONDataBlockReader.h"
32 #include "AliHLTMUONDataBlockWriter.h"
33 #include "AliCDBEntry.h"
34 #include "AliCDBManager.h"
35 #include "TObjString.h"
36 #include "TString.h"
37 #include <cstdlib>
38 #include <cstring>
39 #include <cerrno>
40 #include <cmath>
41 #include <new>
42
43
44 // Helper type for memory allocation.
45 typedef const AliHLTMUONMansoTrackStruct* AliHLTMUONMansoTrackStructP;
46
47
48 ClassImp(AliHLTMUONDecisionComponent);
49
50
51 AliHLTMUONDecisionComponent::AliHLTMUONDecisionComponent() :
52         AliHLTProcessor(),
53         fMaxTracks(1),
54         fTrackCount(0),
55         fTracks(new AliHLTMUONMansoTrackStructP[fMaxTracks]),
56         fLowPtCut(1.),  // 1 GeV/c cut
57         fHighPtCut(2.),  // 2 GeV/c cut
58         fLowMassCut(2.5),  // 2.7 GeV/c^2 cut
59         fHighMassCut(7.),  // 8 GeV/c^2 cut
60         fWarnForUnexpecedBlock(false)
61 {
62         ///
63         /// Default constructor.
64         ///
65 }
66
67
68 AliHLTMUONDecisionComponent::~AliHLTMUONDecisionComponent()
69 {
70         ///
71         /// Default destructor deletes the fTracks array.
72         ///
73         
74         assert(fTracks != NULL);
75         delete [] fTracks;
76 }
77
78
79 const char* AliHLTMUONDecisionComponent::GetComponentID()
80 {
81         ///
82         /// Inherited from AliHLTComponent. Returns the component ID.
83         ///
84         
85         return AliHLTMUONConstants::DecisionComponentId();
86 }
87
88
89 void AliHLTMUONDecisionComponent::GetInputDataTypes(
90                 vector<AliHLTComponentDataType>& list
91         )
92 {
93         ///
94         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
95         ///
96         
97         assert( list.empty() );
98         list.push_back( AliHLTMUONConstants::MansoTracksBlockDataType() );
99 }
100
101
102 AliHLTComponentDataType AliHLTMUONDecisionComponent::GetOutputDataType()
103 {
104         /// Inherited from AliHLTComponent. Returns kAliHLTMultipleDataType
105         /// refer to GetOutputDataTypes for all returned data types.
106         
107         return kAliHLTMultipleDataType;
108 }
109
110
111 int AliHLTMUONDecisionComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
112 {
113         /// Inherited from AliHLTComponent. Returns the output data types.
114         
115         assert( list.empty() );
116         list.push_back( AliHLTMUONConstants::SinglesDecisionBlockDataType() );
117         list.push_back( AliHLTMUONConstants::PairsDecisionBlockDataType() );
118         return 1;
119 }
120
121
122 void AliHLTMUONDecisionComponent::GetOutputDataSize(
123                 unsigned long& constBase, double& inputMultiplier
124         )
125 {
126         ///
127         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
128         ///
129         
130         constBase = sizeof(AliHLTMUONSinglesDecisionBlockStruct);
131         constBase += sizeof(AliHLTMUONPairsDecisionBlockStruct);
132         inputMultiplier = 1;
133 }
134
135
136 AliHLTComponent* AliHLTMUONDecisionComponent::Spawn()
137 {
138         ///
139         /// Inherited from AliHLTComponent. Creates a new object instance.
140         ///
141         
142         return new AliHLTMUONDecisionComponent;
143 }
144
145
146 int AliHLTMUONDecisionComponent::DoInit(int argc, const char** argv)
147 {
148         ///
149         /// Inherited from AliHLTComponent.
150         /// Parses the command line parameters and initialises the component.
151         ///
152         
153         HLTInfo("Initialising dHLT trigger decision component.");
154         
155         bool lowPtCutSet = false;
156         bool highPtCutSet = false;
157         bool lowMassCutSet = false;
158         bool highMassCutSet = false;
159         fWarnForUnexpecedBlock = false;
160         
161         for (int i = 0; i < argc; i++)
162         {
163                 if (strcmp( argv[i], "-lowptcut" ) == 0)
164                 {
165                         if (argc <= i+1)
166                         {
167                                 HLTError("The value for the low pT cut was not specified.");
168                                 return -EINVAL;
169                         }
170                         
171                         char* cpErr = NULL;
172                         double num = strtod(argv[i+1], &cpErr);
173                         if (cpErr == NULL or *cpErr != '\0')
174                         {
175                                 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
176                                 return -EINVAL;
177                         }
178                         fLowPtCut = (AliHLTFloat32_t)num;
179                         lowPtCutSet = true;
180                         
181                         i++;
182                         continue;
183                 }
184                 
185                 if (strcmp( argv[i], "-highptcut" ) == 0)
186                 {
187                         if (argc <= i+1)
188                         {
189                                 HLTError("The value for the high pT cut was not specified.");
190                                 return -EINVAL;
191                         }
192                         
193                         char* cpErr = NULL;
194                         double num = strtod(argv[i+1], &cpErr);
195                         if (cpErr == NULL or *cpErr != '\0')
196                         {
197                                 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
198                                 return -EINVAL;
199                         }
200                         fHighPtCut = (AliHLTFloat32_t)num;
201                         highPtCutSet = true;
202                         
203                         i++;
204                         continue;
205                 }
206                 
207                 if (strcmp( argv[i], "-lowmasscut" ) == 0)
208                 {
209                         if (argc <= i+1)
210                         {
211                                 HLTError("The value for the low invariant mass cut was not specified.");
212                                 return -EINVAL;
213                         }
214                         
215                         char* cpErr = NULL;
216                         double num = strtod(argv[i+1], &cpErr);
217                         if (cpErr == NULL or *cpErr != '\0')
218                         {
219                                 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
220                                 return -EINVAL;
221                         }
222                         fLowMassCut = (AliHLTFloat32_t)num;
223                         lowMassCutSet = true;
224                         
225                         i++;
226                         continue;
227                 }
228                 
229                 if (strcmp( argv[i], "-highmasscut" ) == 0)
230                 {
231                         if (argc <= i+1)
232                         {
233                                 HLTError("The value for the high invariant mass cut was not specified.");
234                                 return -EINVAL;
235                         }
236                         
237                         char* cpErr = NULL;
238                         double num = strtod(argv[i+1], &cpErr);
239                         if (cpErr == NULL or *cpErr != '\0')
240                         {
241                                 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
242                                 return -EINVAL;
243                         }
244                         fHighMassCut = (AliHLTFloat32_t)num;
245                         highMassCutSet = true;
246                         
247                         i++;
248                         continue;
249                 }
250                 
251                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
252                 {
253                         fWarnForUnexpecedBlock = true;
254                         continue;
255                 }
256
257                 HLTError("Unknown option '%s'.", argv[i]);
258                 return -EINVAL;
259         }
260         
261         // Read cut parameters from CDB if they were not specified on the command line.
262         if (not lowPtCutSet or not highPtCutSet or not lowMassCutSet or not highMassCutSet)
263         {
264                 int result = ReadConfigFromCDB(
265                                 NULL,
266                                 not lowPtCutSet, not highPtCutSet,
267                                 not lowMassCutSet, not highMassCutSet
268                         );
269                 if (result != 0) return result;
270         }
271         
272         HLTDebug("Using the following cut parameters:");
273         HLTDebug("              Low pT cut = %f GeV/c", fLowPtCut);
274         HLTDebug("             High pT cut = %f GeV/c", fHighPtCut);
275         HLTDebug("  Low invariant mass cut = %f GeV/c^2", fLowMassCut);
276         HLTDebug(" High invariant mass cut = %f GeV/c^2", fHighMassCut);
277         
278         return 0;
279 }
280
281
282 int AliHLTMUONDecisionComponent::DoDeinit()
283 {
284         ///
285         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
286         ///
287         
288         HLTInfo("Deinitialising dHLT trigger decision component.");
289         return 0;
290 }
291
292
293 int AliHLTMUONDecisionComponent::Reconfigure(const char* cdbEntry, const char* componentId)
294 {
295         /// Inherited from AliHLTComponent. Reconfigures the component from CDB.
296         
297         if (strcmp(componentId, GetComponentID()) == 0)
298         {
299                 HLTInfo("Reading new entries for cut parameters from CDB.");
300                 int result = ReadConfigFromCDB(cdbEntry);
301                 HLTDebug("Using the following new cut parameters:");
302                 HLTDebug("              Low pT cut = %f GeV/c", fLowPtCut);
303                 HLTDebug("             High pT cut = %f GeV/c", fHighPtCut);
304                 HLTDebug("  Low invariant mass cut = %f GeV/c^2", fLowMassCut);
305                 HLTDebug(" High invariant mass cut = %f GeV/c^2", fHighMassCut);
306                 return result;
307         }
308         else
309                 return 0;
310 }
311
312
313 int AliHLTMUONDecisionComponent::DoEvent(
314                 const AliHLTComponentEventData& evtData,
315                 const AliHLTComponentBlockData* blocks,
316                 AliHLTComponentTriggerData& /*trigData*/,
317                 AliHLTUInt8_t* outputPtr,
318                 AliHLTUInt32_t& size,
319                 std::vector<AliHLTComponentBlockData>& outputBlocks
320         )
321 {
322         ///
323         /// Inherited from AliHLTProcessor. Processes the new event data.
324         ///
325         
326         AliHLTUInt32_t specification = 0;  // Contains the output data block spec bits.
327         
328         // Loop over all input blocks in the event with track data and add pointers
329         // to the tracks into the tracks array. These will be used later by the
330         // trigger algorithm to get to the individual tracks.
331         fTrackCount = 0; // reset number of tracks in array.
332         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
333         {
334                 if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
335                 {
336                         // Build up the specification which indicates what DDLs
337                         // contributed to the output data.
338                         specification |= blocks[n].fSpecification;
339                         
340                         AliHLTMUONMansoTracksBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
341                         if (not inblock.BufferSizeOk())
342                         {
343                                 size_t headerSize = sizeof(AliHLTMUONMansoTracksBlockReader::HeaderType);
344                                 if (blocks[n].fSize < headerSize)
345                                 {
346                                         HLTError("Received a manso tracks data block with a size of %d bytes,"
347                                                 " which is smaller than the minimum valid header size of %d bytes."
348                                                 " The block must be corrupt.",
349                                                 blocks[n].fSize, headerSize
350                                         );
351                                         continue;
352                                 }
353                                 
354                                 size_t expectedWidth = sizeof(AliHLTMUONMansoTracksBlockReader::ElementType);
355                                 if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
356                                 {
357                                         HLTError("Received a manso tracks data block with a record"
358                                                 " width of %d bytes, but the expected value is %d bytes."
359                                                 " The block might be corrupt.",
360                                                 inblock.CommonBlockHeader().fRecordWidth, expectedWidth
361                                         );
362                                         continue;
363                                 }
364                                 
365                                 HLTError("Received a manso tracks data block with a size of %d bytes,"
366                                         " but the block header claims the block should be %d bytes."
367                                         " The block might be corrupt.",
368                                         blocks[n].fSize, inblock.BytesUsed()
369                                 );
370                                 continue;
371                         }
372                         
373                         for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
374                         {
375                                 int result = AddTrack(&inblock[i]);
376                                 if (result != 0)
377                                 {
378                                         size = 0; // Important to tell framework that nothing was generated.
379                                         return result;
380                                 }
381                         }
382                 }
383                 else if (blocks[n].fDataType != AliHLTMUONConstants::MansoTracksBlockDataType())
384                 {
385                         // Log a message indicating that we got a data block that we
386                         // do not know how to handle.
387                         char id[kAliHLTComponentDataTypefIDsize+1];
388                         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
389                                 id[i] = blocks[n].fDataType.fID[i];
390                         id[kAliHLTComponentDataTypefIDsize] = '\0';
391                         char origin[kAliHLTComponentDataTypefOriginSize+1];
392                         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
393                                 origin[i] = blocks[n].fDataType.fOrigin[i];
394                         origin[kAliHLTComponentDataTypefOriginSize] = '\0';
395                         
396                         if (fWarnForUnexpecedBlock)
397                                 HLTWarning("Received a data block of a type we cannot handle: %s origin: %s",
398                                         static_cast<char*>(id), static_cast<char*>(origin)
399                                 );
400                         else
401                                 HLTDebug("Received a data block of a type we cannot handle: %s origin: %s",
402                                         static_cast<char*>(id), static_cast<char*>(origin)
403                                 );
404                 }
405         }
406         
407         // Now we can create our two new output data blocks for the single tracks
408         // and track pairs.
409         AliHLTMUONSinglesDecisionBlockWriter singlesBlock(outputPtr, size);
410         
411         if (not singlesBlock.InitCommonHeader())
412         {
413                 Logging(kHLTLogError,
414                         "AliHLTMUONDecisionComponent::DoEvent",
415                         "Buffer overflow",
416                         "The buffer is only %d bytes in size. We need a minimum of"
417                         " %d bytes for the singles output data block.",
418                         size, sizeof(AliHLTMUONSinglesDecisionBlockWriter::HeaderType)
419                 );
420                 size = 0; // Important to tell framework that nothing was generated.
421                 return -ENOBUFS;
422         }
423         
424         if (not singlesBlock.SetNumberOfEntries(fTrackCount))
425         {
426                 AliHLTUInt32_t bytesneeded = sizeof(AliHLTMUONSinglesDecisionBlockWriter::HeaderType)
427                         + fTrackCount * sizeof(AliHLTMUONSinglesDecisionBlockWriter::ElementType);
428                 HLTError("The buffer is only %d bytes in size. We need a minimum of"
429                         " %d bytes for the singles output data block.",
430                         size, bytesneeded
431                 );
432                 size = 0; // Important to tell framework that nothing was generated.
433                 return -ENOBUFS;
434         }
435         
436         AliHLTMUONPairsDecisionBlockWriter pairsBlock(
437                         outputPtr + singlesBlock.BytesUsed(),
438                         size - singlesBlock.BytesUsed()
439                 );
440         
441         if (not pairsBlock.InitCommonHeader())
442         {
443                 Logging(kHLTLogError,
444                         "AliHLTMUONDecisionComponent::DoEvent",
445                         "Buffer overflow",
446                         "The buffer is only %d bytes in size. We need a minimum of"
447                         " %d bytes for the pairs output data block.",
448                         size,
449                         sizeof(AliHLTMUONPairsDecisionBlockWriter::HeaderType) + singlesBlock.BytesUsed()
450                 );
451                 size = 0; // Important to tell framework that nothing was generated.
452                 return -ENOBUFS;
453         }
454         
455         AliHLTUInt32_t numOfPairs = fTrackCount * (fTrackCount-1) / 2;
456         if (not pairsBlock.SetNumberOfEntries(numOfPairs))
457         {
458                 AliHLTUInt32_t bytesneeded = sizeof(AliHLTMUONPairsDecisionBlockWriter::HeaderType)
459                         + fTrackCount * sizeof(AliHLTMUONPairsDecisionBlockWriter::ElementType)
460                         + singlesBlock.BytesUsed();
461                 HLTError("The buffer is only %d bytes in size. We need a minimum of"
462                         " %d bytes for the pairs output data block.",
463                         size, bytesneeded
464                 );
465                 size = 0; // Important to tell framework that nothing was generated.
466                 return -ENOBUFS;
467         }
468         
469         ApplyTriggerAlgorithm(
470                         singlesBlock.BlockHeader(),
471                         singlesBlock.GetArray(),
472                         pairsBlock.BlockHeader(),
473                         pairsBlock.GetArray()
474                 );
475         
476         AliHLTComponentBlockData sbd;
477         FillBlockData(sbd);
478         sbd.fPtr = outputPtr;
479         sbd.fOffset = 0;
480         sbd.fSize = singlesBlock.BytesUsed();
481         sbd.fDataType = AliHLTMUONConstants::SinglesDecisionBlockDataType();
482         sbd.fSpecification = specification;
483         outputBlocks.push_back(sbd);
484         size = singlesBlock.BytesUsed();
485         
486         AliHLTComponentBlockData pbd;
487         FillBlockData(pbd);
488         pbd.fPtr = outputPtr;
489         pbd.fOffset = singlesBlock.BytesUsed();
490         pbd.fSize = pairsBlock.BytesUsed();
491         pbd.fDataType = AliHLTMUONConstants::PairsDecisionBlockDataType();
492         pbd.fSpecification = specification;
493         outputBlocks.push_back(pbd);
494         size += pairsBlock.BytesUsed();
495         
496         return 0;
497 }
498
499
500 int AliHLTMUONDecisionComponent::ReadConfigFromCDB(
501                 const char* path,
502                 bool setLowPtCut, bool setHighPtCut,
503                 bool setLowMassCut, bool setHighMassCut
504         )
505 {
506         /// Reads the cut parameters from the CDB.
507         
508         assert(AliCDBManager::Instance() != NULL);
509         
510         const char* pathToEntry = AliHLTMUONConstants::DecisionComponentCDBPath();
511         if (path != NULL)
512                 pathToEntry = path;
513         
514         AliCDBEntry* entry = AliCDBManager::Instance()->Get(pathToEntry);
515         if (entry == NULL)
516         {
517                 HLTError("Could not get the CDB entry for \"%s\".", pathToEntry);
518                 return -EIO;
519         }
520         
521         TObject* obj = entry->GetObject();
522         if (obj == NULL)
523         {
524                 HLTError("Configuration object for \"%s\" is missing.", pathToEntry);
525                 return -ENOENT;
526         }
527         
528         if (obj->IsA() != TMap::Class())
529         {
530                 HLTError("Wrong type for configuration object in \"%s\". Found a %s but we need a TMap.",
531                         pathToEntry, obj->ClassName()
532                 );
533                 return -EPROTO;
534         }
535         TMap* map = dynamic_cast<TMap*>(obj);
536         
537         if (setLowPtCut)
538         {
539                 TPair* pair = static_cast<TPair*>(map->FindObject("lowptcut"));
540                 if (pair == NULL)
541                 {
542                         HLTError("Configuration object for \"%s\" does not contain the low pT cut value.",
543                                 pathToEntry
544                         );
545                         return -ENOENT;
546                 }
547                 TObject* valueObj = pair->Value();
548                 if (valueObj->IsA() != TObjString::Class())
549                 {
550                         HLTError("The low pT cut parameter found in configuration object \"%s\""
551                                 " is not a TObjString. Found an object of type %s instead.",
552                                 pathToEntry, valueObj->ClassName()
553                         );
554                         return -EPROTO;
555                 }
556                 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
557                 if (not value.IsFloat())
558                 {
559                         HLTError("The low pT cut parameter found in configuration object \"%s\""
560                                 "is not a floating point string; found \"%s\".",
561                                 pathToEntry, value.Data()
562                         );
563                         return -EPROTO;
564                 }
565                 fLowPtCut = (AliHLTFloat32_t) value.Atof();
566         }
567         
568         if (setHighPtCut)
569         {
570                 TPair* pair = static_cast<TPair*>(map->FindObject("highptcut"));
571                 if (pair == NULL)
572                 {
573                         HLTError("Configuration object for \"%s\" does not contain the high pT cut value.",
574                                 pathToEntry
575                         );
576                         return -ENOENT;
577                 }
578                 TObject* valueObj = pair->Value();
579                 if (valueObj->IsA() != TObjString::Class())
580                 {
581                         HLTError("The high pT cut parameter found in configuration object \"%s\""
582                                 " is not a TObjString. Found an object of type %s instead.",
583                                 pathToEntry, valueObj->ClassName()
584                         );
585                         return -EPROTO;
586                 }
587                 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
588                 if (not value.IsFloat())
589                 {
590                         HLTError("The high pT cut parameter found in configuration object \"%s\""
591                                 "is not a floating point string; found \"%s\".",
592                                 pathToEntry, value.Data()
593                         );
594                         return -EPROTO;
595                 }
596                 fHighPtCut = (AliHLTFloat32_t) value.Atof();
597         }
598         
599         if (setLowMassCut)
600         {
601                 TPair* pair = static_cast<TPair*>(map->FindObject("lowmasscut"));
602                 if (pair == NULL)
603                 {
604                         HLTError("Configuration object for \"%s\" does not contain the low invariant mass cut value.",
605                                 pathToEntry
606                         );
607                         return -ENOENT;
608                 }
609                 TObject* valueObj = pair->Value();
610                 if (valueObj->IsA() != TObjString::Class())
611                 {
612                         HLTError("The low invariant mass cut parameter found in configuration object \"%s\""
613                                 " is not a TObjString. Found an object of type %s instead.",
614                                 pathToEntry, valueObj->ClassName()
615                         );
616                         return -EPROTO;
617                 }
618                 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
619                 if (not value.IsFloat())
620                 {
621                         HLTError("The low invariant mass cut parameter found in configuration object \"%s\""
622                                 "is not a floating point string; found \"%s\".",
623                                 pathToEntry, value.Data()
624                         );
625                         return -EPROTO;
626                 }
627                 fLowMassCut = (AliHLTFloat32_t) value.Atof();
628         }
629         
630         if (setHighMassCut)
631         {
632                 TPair* pair = static_cast<TPair*>(map->FindObject("highmasscut"));
633                 if (pair == NULL)
634                 {
635                         HLTError("Configuration object for \"%s\" does not contain the high invariant mass cut value.",
636                                 pathToEntry
637                         );
638                         return -ENOENT;
639                 }
640                 TObject* valueObj = pair->Value();
641                 if (valueObj->IsA() != TObjString::Class())
642                 {
643                         HLTError("The high invariant mass cut parameter found in configuration object \"%s\""
644                                 " is not a TObjString. Found an object of type %s instead.",
645                                 pathToEntry, valueObj->ClassName()
646                         );
647                         return -EPROTO;
648                 }
649                 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
650                 if (not value.IsFloat())
651                 {
652                         HLTError("The high invariant mass cut parameter found in configuration object \"%s\""
653                                 "is not a floating point string; found \"%s\".",
654                                 pathToEntry, value.Data()
655                         );
656                         return -EPROTO;
657                 }
658                 fHighMassCut = (AliHLTFloat32_t) value.Atof();
659         }
660         
661         return 0;
662 }
663
664
665 int AliHLTMUONDecisionComponent::AddTrack(const AliHLTMUONMansoTrackStruct* track)
666 {
667         /// Adds a track to the internal track list for future reference in
668         /// ApplyTriggerAlgorithm when we actually apply the trigger algorithm.
669
670         assert(fTrackCount <= fMaxTracks);
671         assert(fTracks != NULL);
672         
673         if (fTrackCount == fMaxTracks)
674         {
675                 // Buffer full so we need to resize it.
676                 const AliHLTMUONMansoTrackStruct** tmp = NULL;
677                 try
678                 {
679                         tmp = new AliHLTMUONMansoTrackStructP[fMaxTracks+1];
680                 }
681                 catch (const std::bad_alloc&)
682                 {
683                         HLTError("Could not allocate more memory for the track array.");
684                         return -ENOMEM;
685                 }
686                 
687                 // Copy over the exisiting data and then delete the old array.
688                 memcpy(tmp, fTracks, sizeof(AliHLTMUONMansoTrackStructP)*fTrackCount);
689                 delete [] fTracks;
690                 fTracks = tmp;
691                 fMaxTracks = fMaxTracks+1;
692         }
693         
694         fTracks[fTrackCount] = track;
695         fTrackCount++;
696         return 0;
697 }
698
699
700 void AliHLTMUONDecisionComponent::ApplyTriggerAlgorithm(
701                 AliHLTMUONSinglesDecisionBlockStruct& singlesHeader,
702                 AliHLTMUONTrackDecisionStruct* singlesDecision,
703                 AliHLTMUONPairsDecisionBlockStruct& pairsHeader,
704                 AliHLTMUONPairDecisionStruct* pairsDecision
705         )
706 {
707         /// This method applies the dHLT trigger decision algorithm to all the
708         /// tracks found in the input data.
709
710         // Zero the trigger counters for single tracks.
711         singlesHeader.fNlowPt = 0;
712         singlesHeader.fNhighPt = 0;
713
714         // Zero the trigger counters for pairs.
715         pairsHeader.fNunlikeAnyPt = 0;
716         pairsHeader.fNunlikeLowPt = 0;
717         pairsHeader.fNunlikeHighPt = 0;
718         pairsHeader.fNlikeAnyPt = 0;
719         pairsHeader.fNlikeLowPt = 0;
720         pairsHeader.fNlikeHighPt = 0;
721         pairsHeader.fNmassAny = 0;
722         pairsHeader.fNmassLow = 0;
723         pairsHeader.fNmassHigh = 0;
724         
725         // For the single tracks we check if a track has pT larger than either
726         // the low or high pT cut. If it does then we increment the appropriate
727         // counters in the header.
728         for (AliHLTUInt32_t n = 0; n < fTrackCount; n++)
729         {
730                 const AliHLTMUONMansoTrackStruct* track = fTracks[n];
731                 AliHLTMUONTrackDecisionStruct& decision = singlesDecision[n];
732                 
733                 bool passedHighPtCut = false;
734                 bool passedLowPtCut = false;
735                 
736                 AliHLTFloat32_t pt = sqrt(track->fPx * track->fPx + track->fPy * track->fPy);
737                 
738                 if (pt > fHighPtCut)
739                 {
740                         passedHighPtCut = true;
741                         singlesHeader.fNlowPt++;
742                 }
743                 if (pt > fLowPtCut)
744                 {
745                         passedLowPtCut = true;
746                         singlesHeader.fNhighPt++;
747                 }
748                 
749                 decision.fTrackId = track->fId;
750                 decision.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(
751                                 passedHighPtCut, passedLowPtCut
752                         );
753                 decision.fPt = pt;
754         }
755         
756         // Now we generate all the possible pairs of tracks and fill in the
757         // trigger information. This will consist of calculating the invariant
758         // mass for the pair, checking if it passes the low or high mass cut
759         // and incrementing the appropriate statistics.
760         AliHLTUInt32_t currentPair = 0;
761         for (AliHLTUInt32_t i = 0; i < fTrackCount; i++)
762         for (AliHLTUInt32_t j = i+1; j < fTrackCount; j++)
763         {
764                 const AliHLTMUONMansoTrackStruct* tracki = fTracks[i];
765                 const AliHLTMUONMansoTrackStruct* trackj = fTracks[j];
766                 const AliHLTMUONTrackDecisionStruct& trackidecision = singlesDecision[i];
767                 const AliHLTMUONTrackDecisionStruct& trackjdecision = singlesDecision[j];
768                 AliHLTMUONPairDecisionStruct& decision = pairsDecision[currentPair];
769                 
770                 AliHLTFloat32_t muMass = 0.1056583568; // muon mass in GeV/c^2
771                 
772                 AliHLTFloat32_t mass = AliHLTMUONCalculations::ComputeMass(
773                                 muMass, tracki->fPx, tracki->fPy, tracki->fPz,
774                                 muMass, trackj->fPx, trackj->fPy, trackj->fPz
775                         );
776                 
777                 AliHLTMUONParticleSign signi, signj;
778                 bool hitset[4];
779                 AliHLTMUONUtils::UnpackMansoTrackFlags(tracki->fFlags, signi, hitset);
780                 AliHLTMUONUtils::UnpackMansoTrackFlags(trackj->fFlags, signj, hitset);
781                 
782                 AliHLTUInt8_t highPtCount = 0;
783                 if (trackidecision.fPt > fHighPtCut) highPtCount++;
784                 if (trackjdecision.fPt > fHighPtCut) highPtCount++;
785                 AliHLTUInt8_t lowPtCount = 0;
786                 if (trackidecision.fPt > fLowPtCut) lowPtCount++;
787                 if (trackjdecision.fPt > fLowPtCut) lowPtCount++;
788                 
789                 bool unlikeSign = (signi == kSignMinus and signj == kSignPlus) or
790                                   (signi == kSignPlus  and signj == kSignMinus);
791                 
792                 bool passedHighMassCut = false;
793                 bool passedLowMassCut = false;
794                 if (unlikeSign)
795                 {
796                         pairsHeader.fNunlikeAnyPt++;
797                         if (lowPtCount == 2) pairsHeader.fNunlikeLowPt++;
798                         if (highPtCount == 2) pairsHeader.fNunlikeHighPt++;
799                         
800                         if (mass > fHighMassCut)
801                         {
802                                 passedHighMassCut = true;
803                                 if (highPtCount == 2) pairsHeader.fNmassHigh++;
804                         }
805                         if (mass > fLowMassCut)
806                         {
807                                 passedLowMassCut = true;
808                                 pairsHeader.fNmassAny++;
809                                 if (lowPtCount == 2) pairsHeader.fNmassLow++;
810                         }
811                 }
812                 else
813                 {
814                         pairsHeader.fNlikeAnyPt++;
815                         if (lowPtCount == 2) pairsHeader.fNlikeLowPt++;
816                         if (highPtCount == 2) pairsHeader.fNlikeHighPt++;
817                 }
818                 
819                 decision.fTrackAId = tracki->fId;
820                 decision.fTrackBId = trackj->fId;
821                 decision.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(
822                                 passedHighMassCut, passedLowMassCut, unlikeSign,
823                                 highPtCount, lowPtCount
824                         );
825                 decision.fInvMass = mass;
826                 
827                 currentPair++;
828         }
829         
830         assert( currentPair == fTrackCount * (fTrackCount-1) / 2 );
831 }
832