Cleanup of documentation and code.
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONDecisionComponent.cxx
CommitLineData
c9537879 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.
45typedef const AliHLTMUONMansoTrackStruct* AliHLTMUONMansoTrackStructP;
46
47
48ClassImp(AliHLTMUONDecisionComponent);
49
50
51AliHLTMUONDecisionComponent::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
68AliHLTMUONDecisionComponent::~AliHLTMUONDecisionComponent()
69{
70 ///
71 /// Default destructor deletes the fTracks array.
72 ///
73
74 assert(fTracks != NULL);
75 delete [] fTracks;
76}
77
78
79const char* AliHLTMUONDecisionComponent::GetComponentID()
80{
81 ///
82 /// Inherited from AliHLTComponent. Returns the component ID.
83 ///
84
85 return AliHLTMUONConstants::DecisionComponentId();
86}
87
88
89void 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
102AliHLTComponentDataType 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
111int 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
122void 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
136AliHLTComponent* AliHLTMUONDecisionComponent::Spawn()
137{
138 ///
139 /// Inherited from AliHLTComponent. Creates a new object instance.
140 ///
141
142 return new AliHLTMUONDecisionComponent;
143}
144
145
146int 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
282int 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
293int 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
313int 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 {
450e0b36 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
c9537879 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 }
450e0b36 387 else
c9537879 388 {
389 // Log a message indicating that we got a data block that we
390 // do not know how to handle.
c9537879 391 if (fWarnForUnexpecedBlock)
450e0b36 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
c9537879 394 );
395 else
450e0b36 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
c9537879 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
495int 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
660int 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
695void 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