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