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 // Helper type for memory allocation.
45 typedef const AliHLTMUONMansoTrackStruct* AliHLTMUONMansoTrackStructP;
48 ClassImp(AliHLTMUONDecisionComponent);
51 AliHLTMUONDecisionComponent::AliHLTMUONDecisionComponent() :
52 AliHLTMUONProcessor(),
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)
63 /// Default constructor.
68 AliHLTMUONDecisionComponent::~AliHLTMUONDecisionComponent()
71 /// Default destructor deletes the fTracks array.
74 assert(fTracks != NULL);
79 const char* AliHLTMUONDecisionComponent::GetComponentID()
82 /// Inherited from AliHLTComponent. Returns the component ID.
85 return AliHLTMUONConstants::DecisionComponentId();
89 void AliHLTMUONDecisionComponent::GetInputDataTypes(
90 vector<AliHLTComponentDataType>& list
94 /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
97 assert( list.empty() );
98 list.push_back( AliHLTMUONConstants::MansoTracksBlockDataType() );
102 AliHLTComponentDataType AliHLTMUONDecisionComponent::GetOutputDataType()
104 /// Inherited from AliHLTComponent. Returns kAliHLTMultipleDataType
105 /// refer to GetOutputDataTypes for all returned data types.
107 return kAliHLTMultipleDataType;
111 int AliHLTMUONDecisionComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
113 /// Inherited from AliHLTComponent. Returns the output data types.
115 assert( list.empty() );
116 list.push_back( AliHLTMUONConstants::SinglesDecisionBlockDataType() );
117 list.push_back( AliHLTMUONConstants::PairsDecisionBlockDataType() );
122 void AliHLTMUONDecisionComponent::GetOutputDataSize(
123 unsigned long& constBase, double& inputMultiplier
127 /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
130 constBase = sizeof(AliHLTMUONSinglesDecisionBlockStruct);
131 constBase += sizeof(AliHLTMUONPairsDecisionBlockStruct);
132 inputMultiplier = 100;
136 AliHLTComponent* AliHLTMUONDecisionComponent::Spawn()
139 /// Inherited from AliHLTComponent. Creates a new object instance.
142 return new AliHLTMUONDecisionComponent;
146 int AliHLTMUONDecisionComponent::DoInit(int argc, const char** argv)
149 /// Inherited from AliHLTComponent.
150 /// Parses the command line parameters and initialises the component.
153 HLTInfo("Initialising dHLT trigger decision component.");
155 bool lowPtCutSet = false;
156 bool highPtCutSet = false;
157 bool lowMassCutSet = false;
158 bool highMassCutSet = false;
159 fWarnForUnexpecedBlock = false;
161 for (int i = 0; i < argc; i++)
163 if (strcmp( argv[i], "-lowptcut" ) == 0)
167 HLTWarning("Low pT cut parameter was already specified."
168 " Will replace previous value given by -lowptcut."
174 HLTError("The value for the low pT cut was not specified.");
179 double num = strtod(argv[i+1], &cpErr);
180 if (cpErr == NULL or *cpErr != '\0')
182 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
185 fLowPtCut = (AliHLTFloat32_t)num;
192 if (strcmp( argv[i], "-highptcut" ) == 0)
196 HLTWarning("High pT cut parameter was already specified."
197 " Will replace previous value given by -highptcut."
203 HLTError("The value for the high pT cut was not specified.");
208 double num = strtod(argv[i+1], &cpErr);
209 if (cpErr == NULL or *cpErr != '\0')
211 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
214 fHighPtCut = (AliHLTFloat32_t)num;
221 if (strcmp( argv[i], "-lowmasscut" ) == 0)
225 HLTWarning("Low invariant mass cut parameter was already specified."
226 " Will replace previous value given by -lowmasscut."
232 HLTError("The value for the low invariant mass cut was not specified.");
237 double num = strtod(argv[i+1], &cpErr);
238 if (cpErr == NULL or *cpErr != '\0')
240 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
243 fLowMassCut = (AliHLTFloat32_t)num;
244 lowMassCutSet = true;
250 if (strcmp( argv[i], "-highmasscut" ) == 0)
254 HLTWarning("High invariant mass cut parameter was already specified."
255 " Will replace previous value given by -highmasscut."
261 HLTError("The value for the high invariant mass cut was not specified.");
266 double num = strtod(argv[i+1], &cpErr);
267 if (cpErr == NULL or *cpErr != '\0')
269 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
272 fHighMassCut = (AliHLTFloat32_t)num;
273 highMassCutSet = true;
279 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
281 fWarnForUnexpecedBlock = true;
285 HLTError("Unknown option '%s'.", argv[i]);
289 // Read cut parameters from CDB if they were not specified on the command line.
290 if (not lowPtCutSet or not highPtCutSet or not lowMassCutSet or not highMassCutSet)
292 int result = ReadConfigFromCDB(
294 not lowPtCutSet, not highPtCutSet,
295 not lowMassCutSet, not highMassCutSet
297 if (result != 0) return result;
300 HLTDebug("Using the following cut parameters:");
301 HLTDebug(" Low pT cut = %f GeV/c", fLowPtCut);
302 HLTDebug(" High pT cut = %f GeV/c", fHighPtCut);
303 HLTDebug(" Low invariant mass cut = %f GeV/c^2", fLowMassCut);
304 HLTDebug(" High invariant mass cut = %f GeV/c^2", fHighMassCut);
310 int AliHLTMUONDecisionComponent::DoDeinit()
313 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
316 HLTInfo("Deinitialising dHLT trigger decision component.");
321 int AliHLTMUONDecisionComponent::Reconfigure(const char* cdbEntry, const char* componentId)
323 /// Inherited from AliHLTComponent. Reconfigures the component from CDB.
325 if (strcmp(componentId, GetComponentID()) == 0)
327 HLTInfo("Reading new entries for cut parameters from CDB.");
328 int result = ReadConfigFromCDB(cdbEntry);
329 HLTDebug("Using the following new cut parameters:");
330 HLTDebug(" Low pT cut = %f GeV/c", fLowPtCut);
331 HLTDebug(" High pT cut = %f GeV/c", fHighPtCut);
332 HLTDebug(" Low invariant mass cut = %f GeV/c^2", fLowMassCut);
333 HLTDebug(" High invariant mass cut = %f GeV/c^2", fHighMassCut);
341 int AliHLTMUONDecisionComponent::DoEvent(
342 const AliHLTComponentEventData& evtData,
343 const AliHLTComponentBlockData* blocks,
344 AliHLTComponentTriggerData& /*trigData*/,
345 AliHLTUInt8_t* outputPtr,
346 AliHLTUInt32_t& size,
347 std::vector<AliHLTComponentBlockData>& outputBlocks
351 /// Inherited from AliHLTProcessor. Processes the new event data.
354 AliHLTUInt32_t specification = 0; // Contains the output data block spec bits.
356 // Loop over all input blocks in the event with track data and add pointers
357 // to the tracks into the tracks array. These will be used later by the
358 // trigger algorithm to get to the individual tracks.
359 fTrackCount = 0; // reset number of tracks in array.
360 for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
362 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
363 n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
366 if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
368 // Build up the specification which indicates what DDLs
369 // contributed to the output data.
370 specification |= blocks[n].fSpecification;
372 AliHLTMUONMansoTracksBlockReader inblock(
373 reinterpret_cast<char*>(blocks[n].fPtr) + blocks[n].fOffset,
376 if (not BlockStructureOk(inblock)) continue;
378 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
380 int result = AddTrack(&inblock[i]);
383 size = 0; // Important to tell framework that nothing was generated.
390 // Log a message indicating that we got a data block that we
391 // do not know how to handle.
392 if (fWarnForUnexpecedBlock)
393 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
394 DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
397 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
398 DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
403 // Now we can create our two new output data blocks for the single tracks
405 AliHLTMUONSinglesDecisionBlockWriter singlesBlock(outputPtr, size);
407 if (not singlesBlock.InitCommonHeader())
409 Logging(kHLTLogError,
410 "AliHLTMUONDecisionComponent::DoEvent",
412 "The buffer is only %d bytes in size. We need a minimum of"
413 " %d bytes for the singles output data block.",
414 size, sizeof(AliHLTMUONSinglesDecisionBlockWriter::HeaderType)
416 size = 0; // Important to tell framework that nothing was generated.
420 if (not singlesBlock.SetNumberOfEntries(fTrackCount))
422 AliHLTUInt32_t bytesneeded = sizeof(AliHLTMUONSinglesDecisionBlockWriter::HeaderType)
423 + fTrackCount * sizeof(AliHLTMUONSinglesDecisionBlockWriter::ElementType);
424 HLTError("The buffer is only %d bytes in size. We need a minimum of"
425 " %d bytes for the singles output data block.",
428 size = 0; // Important to tell framework that nothing was generated.
432 AliHLTMUONPairsDecisionBlockWriter pairsBlock(
433 outputPtr + singlesBlock.BytesUsed(),
434 size - singlesBlock.BytesUsed()
437 if (not pairsBlock.InitCommonHeader())
439 Logging(kHLTLogError,
440 "AliHLTMUONDecisionComponent::DoEvent",
442 "The buffer is only %d bytes in size. We need a minimum of"
443 " %d bytes for the pairs output data block.",
445 sizeof(AliHLTMUONPairsDecisionBlockWriter::HeaderType) + singlesBlock.BytesUsed()
447 size = 0; // Important to tell framework that nothing was generated.
451 AliHLTUInt32_t numOfPairs = fTrackCount * (fTrackCount-1) / 2;
452 if (not pairsBlock.SetNumberOfEntries(numOfPairs))
454 AliHLTUInt32_t bytesneeded = sizeof(AliHLTMUONPairsDecisionBlockWriter::HeaderType)
455 + numOfPairs * sizeof(AliHLTMUONPairsDecisionBlockWriter::ElementType)
456 + singlesBlock.BytesUsed();
457 HLTError("The buffer is only %d bytes in size. We need a minimum of"
458 " %d bytes for the pairs output data block.",
461 size = 0; // Important to tell framework that nothing was generated.
465 ApplyTriggerAlgorithm(
466 singlesBlock.BlockHeader(),
467 singlesBlock.GetArray(),
468 pairsBlock.BlockHeader(),
469 pairsBlock.GetArray()
472 AliHLTComponentBlockData sbd;
474 sbd.fPtr = outputPtr;
476 sbd.fSize = singlesBlock.BytesUsed();
477 sbd.fDataType = AliHLTMUONConstants::SinglesDecisionBlockDataType();
478 sbd.fSpecification = specification;
479 outputBlocks.push_back(sbd);
480 size = singlesBlock.BytesUsed();
482 AliHLTComponentBlockData pbd;
484 pbd.fPtr = outputPtr;
485 pbd.fOffset = singlesBlock.BytesUsed();
486 pbd.fSize = pairsBlock.BytesUsed();
487 pbd.fDataType = AliHLTMUONConstants::PairsDecisionBlockDataType();
488 pbd.fSpecification = specification;
489 outputBlocks.push_back(pbd);
490 size += pairsBlock.BytesUsed();
496 int AliHLTMUONDecisionComponent::ReadConfigFromCDB(
498 bool setLowPtCut, bool setHighPtCut,
499 bool setLowMassCut, bool setHighMassCut
502 /// Reads the cut parameters from the CDB.
503 /// \param path Indicates the partial (or relative) path to the CDB entry.
505 assert(AliCDBManager::Instance() != NULL);
507 const char* pathToEntry = AliHLTMUONConstants::DecisionComponentCDBPath();
512 int result = FetchTMapFromCDB(pathToEntry, map);
513 if (result != 0) return result;
518 result = GetFloatFromTMap(map, "lowptcut", value, pathToEntry, "low pT cut");
519 if (result != 0) return result;
520 fLowPtCut = (AliHLTFloat32_t) value;
526 result = GetFloatFromTMap(map, "highptcut", value, pathToEntry, "high pT cut");
527 if (result != 0) return result;
528 fHighPtCut = (AliHLTFloat32_t) value;
534 result = GetFloatFromTMap(map, "lowmasscut", value, pathToEntry, "low invariant mass cut");
535 if (result != 0) return result;
536 fLowMassCut = (AliHLTFloat32_t) value;
542 result = GetFloatFromTMap(map, "highmasscut", value, pathToEntry, "high invariant mass cut");
543 if (result != 0) return result;
544 fHighMassCut = (AliHLTFloat32_t) value;
551 int AliHLTMUONDecisionComponent::AddTrack(const AliHLTMUONMansoTrackStruct* track)
553 /// Adds a track to the internal track list for future reference in
554 /// ApplyTriggerAlgorithm when we actually apply the trigger algorithm.
556 assert(fTrackCount <= fMaxTracks);
557 assert(fTracks != NULL);
559 if (fTrackCount == fMaxTracks)
561 // Buffer full so we need to resize it.
562 const AliHLTMUONMansoTrackStruct** tmp = NULL;
565 tmp = new AliHLTMUONMansoTrackStructP[fMaxTracks+1];
567 catch (const std::bad_alloc&)
569 HLTError("Could not allocate more memory for the track array.");
573 // Copy over the exisiting data and then delete the old array.
574 memcpy(tmp, fTracks, sizeof(AliHLTMUONMansoTrackStructP)*fTrackCount);
577 fMaxTracks = fMaxTracks+1;
580 fTracks[fTrackCount] = track;
586 void AliHLTMUONDecisionComponent::ApplyTriggerAlgorithm(
587 AliHLTMUONSinglesDecisionBlockStruct& singlesHeader,
588 AliHLTMUONTrackDecisionStruct* singlesDecision,
589 AliHLTMUONPairsDecisionBlockStruct& pairsHeader,
590 AliHLTMUONPairDecisionStruct* pairsDecision
593 /// This method applies the dHLT trigger decision algorithm to all the
594 /// tracks found in the input data.
596 // Zero the trigger counters for single tracks.
597 singlesHeader.fNlowPt = 0;
598 singlesHeader.fNhighPt = 0;
600 // Zero the trigger counters for pairs.
601 pairsHeader.fNunlikeAnyPt = 0;
602 pairsHeader.fNunlikeLowPt = 0;
603 pairsHeader.fNunlikeHighPt = 0;
604 pairsHeader.fNlikeAnyPt = 0;
605 pairsHeader.fNlikeLowPt = 0;
606 pairsHeader.fNlikeHighPt = 0;
607 pairsHeader.fNmassAny = 0;
608 pairsHeader.fNmassLow = 0;
609 pairsHeader.fNmassHigh = 0;
611 // For the single tracks we check if a track has pT larger than either
612 // the low or high pT cut. If it does then we increment the appropriate
613 // counters in the header.
614 for (AliHLTUInt32_t n = 0; n < fTrackCount; n++)
616 const AliHLTMUONMansoTrackStruct* track = fTracks[n];
617 AliHLTMUONTrackDecisionStruct& decision = singlesDecision[n];
619 bool passedHighPtCut = false;
620 bool passedLowPtCut = false;
622 AliHLTFloat32_t pt = sqrt(track->fPx * track->fPx + track->fPy * track->fPy);
626 passedHighPtCut = true;
627 singlesHeader.fNhighPt++;
631 passedLowPtCut = true;
632 singlesHeader.fNlowPt++;
635 decision.fTrackId = track->fId;
636 decision.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(
637 passedHighPtCut, passedLowPtCut
642 // Now we generate all the possible pairs of tracks and fill in the
643 // trigger information. This will consist of calculating the invariant
644 // mass for the pair, checking if it passes the low or high mass cut
645 // and incrementing the appropriate statistics.
646 AliHLTUInt32_t currentPair = 0;
647 for (AliHLTUInt32_t i = 0; i < fTrackCount; i++)
648 for (AliHLTUInt32_t j = i+1; j < fTrackCount; j++)
650 const AliHLTMUONMansoTrackStruct* tracki = fTracks[i];
651 const AliHLTMUONMansoTrackStruct* trackj = fTracks[j];
652 const AliHLTMUONTrackDecisionStruct& trackidecision = singlesDecision[i];
653 const AliHLTMUONTrackDecisionStruct& trackjdecision = singlesDecision[j];
654 AliHLTMUONPairDecisionStruct& decision = pairsDecision[currentPair];
656 AliHLTFloat32_t muMass = 0.1056583568; // muon mass in GeV/c^2
658 AliHLTFloat32_t mass = AliHLTMUONCalculations::ComputeMass(
659 muMass, tracki->fPx, tracki->fPy, tracki->fPz,
660 muMass, trackj->fPx, trackj->fPy, trackj->fPz
663 AliHLTMUONParticleSign signi, signj;
665 AliHLTMUONUtils::UnpackMansoTrackFlags(tracki->fFlags, signi, hitset);
666 AliHLTMUONUtils::UnpackMansoTrackFlags(trackj->fFlags, signj, hitset);
668 AliHLTUInt8_t highPtCount = 0;
669 if (trackidecision.fPt > fHighPtCut) highPtCount++;
670 if (trackjdecision.fPt > fHighPtCut) highPtCount++;
671 AliHLTUInt8_t lowPtCount = 0;
672 if (trackidecision.fPt > fLowPtCut) lowPtCount++;
673 if (trackjdecision.fPt > fLowPtCut) lowPtCount++;
675 bool unlikeSign = (signi == kSignMinus and signj == kSignPlus) or
676 (signi == kSignPlus and signj == kSignMinus);
678 bool passedHighMassCut = false;
679 bool passedLowMassCut = false;
682 pairsHeader.fNunlikeAnyPt++;
683 if (lowPtCount == 2) pairsHeader.fNunlikeLowPt++;
684 if (highPtCount == 2) pairsHeader.fNunlikeHighPt++;
686 if (mass > fHighMassCut)
688 passedHighMassCut = true;
689 if (highPtCount == 2) pairsHeader.fNmassHigh++;
691 if (mass > fLowMassCut)
693 passedLowMassCut = true;
694 pairsHeader.fNmassAny++;
695 if (lowPtCount == 2) pairsHeader.fNmassLow++;
700 pairsHeader.fNlikeAnyPt++;
701 if (lowPtCount == 2) pairsHeader.fNlikeLowPt++;
702 if (highPtCount == 2) pairsHeader.fNlikeHighPt++;
705 decision.fTrackAId = tracki->fId;
706 decision.fTrackBId = trackj->fId;
707 decision.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(
708 passedHighMassCut, passedLowMassCut, unlikeSign,
709 highPtCount, lowPtCount
711 decision.fInvMass = mass;
716 assert( currentPair == fTrackCount * (fTrackCount-1) / 2 );