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