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