1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Artur Szostak <artursz@iafrica.com> *
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 **************************************************************************/
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.
25 // class documentation is in the header file.
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"
44 ClassImp(AliHLTMUONDecisionComponent);
47 AliHLTMUONDecisionComponent::AliHLTMUONDecisionComponent() :
48 AliHLTMUONProcessor(),
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),
59 fLowMassCutSet(false),
60 fHighMassCutSet(false),
61 fFillSinglesDetail(false),
62 fFillPairsDetail(false)
65 /// Default constructor.
70 AliHLTMUONDecisionComponent::~AliHLTMUONDecisionComponent()
73 /// Default destructor deletes the fTracks array.
76 assert(fTracks != NULL);
81 const char* AliHLTMUONDecisionComponent::GetComponentID()
84 /// Inherited from AliHLTComponent. Returns the component ID.
87 return AliHLTMUONConstants::DecisionComponentId();
91 void AliHLTMUONDecisionComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
94 /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
97 assert( list.empty() );
98 list.push_back( AliHLTMUONConstants::MansoTracksBlockDataType() );
99 list.push_back( AliHLTMUONConstants::TracksBlockDataType() );
103 AliHLTComponentDataType AliHLTMUONDecisionComponent::GetOutputDataType()
105 /// Inherited from AliHLTComponent. Returns kAliHLTMultipleDataType
106 /// refer to GetOutputDataTypes for all returned data types.
108 return kAliHLTMultipleDataType;
112 int AliHLTMUONDecisionComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
114 /// Inherited from AliHLTComponent. Returns the output data types.
116 assert( list.empty() );
117 list.push_back( AliHLTMUONConstants::SinglesDecisionBlockDataType() );
118 list.push_back( AliHLTMUONConstants::PairsDecisionBlockDataType() );
123 void AliHLTMUONDecisionComponent::GetOutputDataSize(
124 unsigned long& constBase, double& inputMultiplier
128 /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
131 constBase = sizeof(AliHLTMUONSinglesDecisionBlockStruct);
132 constBase += sizeof(AliHLTMUONPairsDecisionBlockStruct) + 1024*1024;
133 inputMultiplier = 100;
137 AliHLTComponent* AliHLTMUONDecisionComponent::Spawn()
140 /// Inherited from AliHLTComponent. Creates a new object instance.
143 return new AliHLTMUONDecisionComponent;
147 int AliHLTMUONDecisionComponent::DoInit(int argc, const char** argv)
150 /// Inherited from AliHLTComponent.
151 /// Parses the command line parameters and initialises the component.
154 HLTInfo("Initialising dHLT trigger decision component.");
156 // Inherit the parents functionality.
157 int result = AliHLTMUONProcessor::DoInit(argc, argv);
158 if (result != 0) return result;
160 fWarnForUnexpecedBlock = false;
161 fLowPtCutSet = false;
162 fHighPtCutSet = false;
163 fLowMassCutSet = false;
164 fHighMassCutSet = false;
165 fFillSinglesDetail = true;
166 fFillPairsDetail = true;
168 for (int i = 0; i < argc; i++)
170 if (ArgumentAlreadyHandled(i, argv[i])) continue;
172 if (strcmp( argv[i], "-lowptcut" ) == 0)
176 HLTWarning("Low pT cut parameter was already specified."
177 " Will replace previous value given by -lowptcut."
183 HLTError("The value for the low pT cut was not specified.");
188 double num = strtod(argv[i+1], &cpErr);
189 if (cpErr == NULL or *cpErr != '\0')
191 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
194 fLowPtCut = (AliHLTFloat32_t)num;
201 if (strcmp( argv[i], "-highptcut" ) == 0)
205 HLTWarning("High pT cut parameter was already specified."
206 " Will replace previous value given by -highptcut."
212 HLTError("The value for the high pT cut was not specified.");
217 double num = strtod(argv[i+1], &cpErr);
218 if (cpErr == NULL or *cpErr != '\0')
220 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
223 fHighPtCut = (AliHLTFloat32_t)num;
224 fHighPtCutSet = true;
230 if (strcmp( argv[i], "-lowmasscut" ) == 0)
234 HLTWarning("Low invariant mass cut parameter was already specified."
235 " Will replace previous value given by -lowmasscut."
241 HLTError("The value for the low invariant mass cut was not specified.");
246 double num = strtod(argv[i+1], &cpErr);
247 if (cpErr == NULL or *cpErr != '\0')
249 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
252 fLowMassCut = (AliHLTFloat32_t)num;
253 fLowMassCutSet = true;
259 if (strcmp( argv[i], "-highmasscut" ) == 0)
263 HLTWarning("High invariant mass cut parameter was already specified."
264 " Will replace previous value given by -highmasscut."
270 HLTError("The value for the high invariant mass cut was not specified.");
275 double num = strtod(argv[i+1], &cpErr);
276 if (cpErr == NULL or *cpErr != '\0')
278 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
281 fHighMassCut = (AliHLTFloat32_t)num;
282 fHighMassCutSet = true;
288 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
290 fWarnForUnexpecedBlock = true;
294 if (strcmp( argv[i], "-no_singles_detail" ) == 0)
296 fFillSinglesDetail = false;
300 if (strcmp( argv[i], "-no_pairs_detail" ) == 0)
302 fFillPairsDetail = false;
306 HLTError("Unknown option '%s'.", argv[i]);
310 if (not DelaySetup())
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)
315 HLTInfo("Loading cut parameters from CDB.");
316 result = ReadConfigFromCDB(
317 not fLowPtCutSet, not fHighPtCutSet,
318 not fLowMassCutSet, not fHighMassCutSet
320 if (result != 0) return result;
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);
338 int AliHLTMUONDecisionComponent::DoDeinit()
341 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
344 HLTInfo("Deinitialising dHLT trigger decision component.");
349 int AliHLTMUONDecisionComponent::Reconfigure(const char* cdbEntry, const char* componentId)
351 /// Inherited from AliHLTComponent. Reconfigures the component from CDB.
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.
359 TString path = cdbEntry;
360 bool givenConfigPath = (path == AliHLTMUONConstants::DecisionComponentCDBPath());
362 if (cdbEntry == NULL or givenConfigPath)
364 HLTInfo("Reading new configuration entries from CDB for component '%s'.", componentId);
365 int result = ReadConfigFromCDB();
366 if (result != 0) return result;
373 int AliHLTMUONDecisionComponent::ReadPreprocessorValues(const char* modules)
375 /// Inherited from AliHLTComponent.
376 /// Updates the configuration of this component if HLT or ALL has been
377 /// specified in the 'modules' list.
379 TString mods = modules;
380 if (mods.Contains("ALL"))
382 return Reconfigure(NULL, GetComponentID());
384 if (mods.Contains("HLT"))
386 return Reconfigure(AliHLTMUONConstants::DecisionComponentCDBPath(), GetComponentID());
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
402 /// Inherited from AliHLTProcessor. Processes the new event data.
405 // Initialise the cut parameters from CDB if we were requested to
406 // initialise only when the first event was received.
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)
413 HLTInfo("Loading cut parameters from CDB.");
414 int result = ReadConfigFromCDB(
415 not fLowPtCutSet, not fHighPtCutSet,
416 not fLowMassCutSet, not fHighMassCutSet
418 if (result != 0) return result;
424 AliHLTUInt32_t specification = 0; // Contains the output data block spec bits.
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++)
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
436 if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
438 // Build up the specification which indicates what DDLs
439 // contributed to the output data.
440 specification |= blocks[n].fSpecification;
442 AliHLTMUONMansoTracksBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
443 if (not BlockStructureOk(inblock))
445 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
449 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
451 int result = AddTrack(&inblock[i]);
454 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
455 size = 0; // Important to tell framework that nothing was generated.
460 else if (blocks[n].fDataType == AliHLTMUONConstants::TracksBlockDataType())
462 specification |= blocks[n].fSpecification;
464 AliHLTMUONTracksBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
465 if (not BlockStructureOk(inblock))
467 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
471 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
473 int result = AddTrack(&inblock[i]);
476 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
477 size = 0; // Important to tell framework that nothing was generated.
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
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
499 // Now we can create our two new output data blocks for the single tracks
501 AliHLTMUONSinglesDecisionBlockWriter singlesBlock(outputPtr, size);
503 if (not singlesBlock.InitCommonHeader())
505 Logging(kHLTLogError,
506 "AliHLTMUONDecisionComponent::DoEvent",
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)
512 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
513 size = 0; // Important to tell framework that nothing was generated.
517 AliHLTUInt32_t numOfTracks = fTrackCount;
518 if (not fFillSinglesDetail) numOfTracks = 0;
519 if (not singlesBlock.SetNumberOfEntries(numOfTracks))
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.",
527 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
528 size = 0; // Important to tell framework that nothing was generated.
532 AliHLTMUONPairsDecisionBlockWriter pairsBlock(
533 outputPtr + singlesBlock.BytesUsed(),
534 size - singlesBlock.BytesUsed()
537 if (not pairsBlock.InitCommonHeader())
539 Logging(kHLTLogError,
540 "AliHLTMUONDecisionComponent::DoEvent",
542 "The buffer is only %d bytes in size. We need a minimum of"
543 " %d bytes for the pairs output data block.",
545 sizeof(AliHLTMUONPairsDecisionBlockWriter::HeaderType) + singlesBlock.BytesUsed()
547 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
548 size = 0; // Important to tell framework that nothing was generated.
552 AliHLTUInt32_t numOfPairs = fTrackCount * (fTrackCount-1) / 2;
553 if (not fFillPairsDetail) numOfPairs = 0;
554 if (not pairsBlock.SetNumberOfEntries(numOfPairs))
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.",
563 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
564 size = 0; // Important to tell framework that nothing was generated.
568 ApplyTriggerAlgorithm(
569 singlesBlock.BlockHeader(),
570 singlesBlock.GetArray(),
571 pairsBlock.BlockHeader(),
572 pairsBlock.GetArray()
575 AliHLTComponentBlockData sbd;
577 sbd.fPtr = outputPtr;
579 sbd.fSize = singlesBlock.BytesUsed();
580 sbd.fDataType = AliHLTMUONConstants::SinglesDecisionBlockDataType();
581 sbd.fSpecification = specification;
582 outputBlocks.push_back(sbd);
583 size = singlesBlock.BytesUsed();
585 AliHLTComponentBlockData 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();
599 int AliHLTMUONDecisionComponent::ReadConfigFromCDB(
600 bool setLowPtCut, bool setHighPtCut,
601 bool setLowMassCut, bool setHighMassCut
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.
611 assert(AliCDBManager::Instance() != NULL);
613 const char* pathToEntry = AliHLTMUONConstants::DecisionComponentCDBPath();
616 int result = FetchTMapFromCDB(pathToEntry, map);
617 if (result != 0) return result;
622 result = GetFloatFromTMap(map, "lowptcut", value, pathToEntry, "low pT cut");
623 if (result != 0) return result;
624 fLowPtCut = (AliHLTFloat32_t) value;
630 result = GetFloatFromTMap(map, "highptcut", value, pathToEntry, "high pT cut");
631 if (result != 0) return result;
632 fHighPtCut = (AliHLTFloat32_t) value;
638 result = GetFloatFromTMap(map, "lowmasscut", value, pathToEntry, "low invariant mass cut");
639 if (result != 0) return result;
640 fLowMassCut = (AliHLTFloat32_t) value;
646 result = GetFloatFromTMap(map, "highmasscut", value, pathToEntry, "high invariant mass cut");
647 if (result != 0) return result;
648 fHighMassCut = (AliHLTFloat32_t) value;
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);
661 AliHLTMUONDecisionComponent::AliTrackInfo* AliHLTMUONDecisionComponent::NewTrack()
663 /// Create and return a new element in fTracks.
665 assert(fTrackCount <= fMaxTracks);
666 assert(fTracks != NULL);
668 if (fTrackCount == fMaxTracks)
670 // Buffer full so we need to resize it.
671 AliTrackInfo* tmp = NULL;
674 tmp = new AliTrackInfo[fMaxTracks+16];
676 catch (const std::bad_alloc&)
678 HLTError("Could not allocate more memory for the internal track array.");
682 // Copy over the exisiting data and then delete the old array.
683 memcpy(tmp, fTracks, sizeof(AliTrackInfo)*fTrackCount);
686 fMaxTracks = fMaxTracks+16;
690 return &fTracks[fTrackCount-1];
694 int AliHLTMUONDecisionComponent::AddTrack(const AliHLTMUONTrackStruct* track)
696 /// Adds a track to the internal track list for future reference in
697 /// ApplyTriggerAlgorithm when we actually apply the trigger algorithm.
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;
706 AliHLTMUONUtils::UnpackTrackFlags(track->fFlags, buf->fSign, hitset);
711 int AliHLTMUONDecisionComponent::AddTrack(const AliHLTMUONMansoTrackStruct* track)
713 /// Adds a track to the internal track list for future reference in
714 /// ApplyTriggerAlgorithm when we actually apply the trigger algorithm.
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;
723 AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, buf->fSign, hitset);
728 int AliHLTMUONDecisionComponent::ApplyTriggerAlgorithm(
729 AliHLTMUONSinglesDecisionBlockStruct& singlesHeader,
730 AliHLTMUONTrackDecisionStruct* singlesDecision,
731 AliHLTMUONPairsDecisionBlockStruct& pairsHeader,
732 AliHLTMUONPairDecisionStruct* pairsDecision
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.
739 // Zero the trigger counters for single tracks.
740 singlesHeader.fNlowPt = 0;
741 singlesHeader.fNhighPt = 0;
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;
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)
761 ptValues = new AliHLTFloat32_t[fTrackCount];
763 catch(const std::bad_alloc&)
765 HLTError("Could not allocate memory buffer for pT values.");
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++)
775 const AliTrackInfo* track = &fTracks[n];
777 bool passedHighPtCut = false;
778 bool passedLowPtCut = false;
780 AliHLTFloat32_t pt = sqrt(track->fPx * track->fPx + track->fPy * track->fPy);
784 passedHighPtCut = true;
785 singlesHeader.fNhighPt++;
789 passedLowPtCut = true;
790 singlesHeader.fNlowPt++;
793 if (fFillSinglesDetail)
795 AliHLTMUONTrackDecisionStruct& decision = singlesDecision[n];
796 decision.fTrackId = track->fId;
797 decision.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(
798 passedHighPtCut, passedLowPtCut
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++)
816 const AliTrackInfo* tracki = &fTracks[i];
817 const AliTrackInfo* trackj = &fTracks[j];
819 AliHLTFloat32_t muMass = 0.1056583568; // muon mass in GeV/c^2
821 AliHLTFloat32_t mass = AliHLTMUONCalculations::ComputeMass(
822 muMass, tracki->fPx, tracki->fPy, tracki->fPz,
823 muMass, trackj->fPx, trackj->fPy, trackj->fPz
826 AliHLTMUONParticleSign signi = tracki->fSign;
827 AliHLTMUONParticleSign signj = trackj->fSign;
829 AliHLTUInt8_t highPtCount = 0;
830 AliHLTUInt8_t lowPtCount = 0;
831 if (fFillSinglesDetail)
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++;
842 if (ptValues[i] > fHighPtCut) highPtCount++;
843 if (ptValues[j] > fHighPtCut) highPtCount++;
844 if (ptValues[i] > fLowPtCut) lowPtCount++;
845 if (ptValues[j] > fLowPtCut) lowPtCount++;
848 bool unlikeSign = (signi == kSignMinus and signj == kSignPlus) or
849 (signi == kSignPlus and signj == kSignMinus);
851 bool passedHighMassCut = false;
852 bool passedLowMassCut = false;
855 pairsHeader.fNunlikeAnyPt++;
856 if (lowPtCount == 2) pairsHeader.fNunlikeLowPt++;
857 if (highPtCount == 2) pairsHeader.fNunlikeHighPt++;
859 if (mass > fHighMassCut)
861 passedHighMassCut = true;
862 if (highPtCount == 2) pairsHeader.fNmassHigh++;
864 if (mass > fLowMassCut)
866 passedLowMassCut = true;
867 pairsHeader.fNmassAny++;
868 if (lowPtCount == 2) pairsHeader.fNmassLow++;
873 pairsHeader.fNlikeAnyPt++;
874 if (lowPtCount == 2) pairsHeader.fNlikeLowPt++;
875 if (highPtCount == 2) pairsHeader.fNlikeHighPt++;
878 if (fFillPairsDetail)
880 AliHLTMUONPairDecisionStruct& decision = pairsDecision[currentPair];
882 decision.fTrackAId = tracki->fId;
883 decision.fTrackBId = trackj->fId;
884 decision.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(
885 passedHighMassCut, passedLowMassCut, unlikeSign,
886 highPtCount, lowPtCount
888 decision.fInvMass = mass;
894 assert( fFillPairsDetail == false or (fFillPairsDetail == true and currentPair == fTrackCount * (fTrackCount-1) / 2) );
896 if (not fFillSinglesDetail)
898 assert(ptValues != NULL);