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