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() :
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);
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 HLTError("The value for the low pT cut was not specified.");
172 double num = strtod(argv[i+1], &cpErr);
173 if (cpErr == NULL or *cpErr != '\0')
175 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
178 fLowPtCut = (AliHLTFloat32_t)num;
185 if (strcmp( argv[i], "-highptcut" ) == 0)
189 HLTError("The value for the high pT cut was not specified.");
194 double num = strtod(argv[i+1], &cpErr);
195 if (cpErr == NULL or *cpErr != '\0')
197 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
200 fHighPtCut = (AliHLTFloat32_t)num;
207 if (strcmp( argv[i], "-lowmasscut" ) == 0)
211 HLTError("The value for the low invariant mass cut was not specified.");
216 double num = strtod(argv[i+1], &cpErr);
217 if (cpErr == NULL or *cpErr != '\0')
219 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
222 fLowMassCut = (AliHLTFloat32_t)num;
223 lowMassCutSet = true;
229 if (strcmp( argv[i], "-highmasscut" ) == 0)
233 HLTError("The value for the high invariant mass cut was not specified.");
238 double num = strtod(argv[i+1], &cpErr);
239 if (cpErr == NULL or *cpErr != '\0')
241 HLTError("Cannot convert '%s' to a floating point number.", argv[i+1]);
244 fHighMassCut = (AliHLTFloat32_t)num;
245 highMassCutSet = true;
251 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
253 fWarnForUnexpecedBlock = true;
257 HLTError("Unknown option '%s'.", argv[i]);
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)
264 int result = ReadConfigFromCDB(
266 not lowPtCutSet, not highPtCutSet,
267 not lowMassCutSet, not highMassCutSet
269 if (result != 0) return result;
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);
282 int AliHLTMUONDecisionComponent::DoDeinit()
285 /// Inherited from AliHLTComponent. Performs a cleanup of the component.
288 HLTInfo("Deinitialising dHLT trigger decision component.");
293 int AliHLTMUONDecisionComponent::Reconfigure(const char* cdbEntry, const char* componentId)
295 /// Inherited from AliHLTComponent. Reconfigures the component from CDB.
297 if (strcmp(componentId, GetComponentID()) == 0)
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);
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
323 /// Inherited from AliHLTProcessor. Processes the new event data.
326 AliHLTUInt32_t specification = 0; // Contains the output data block spec bits.
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++)
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
338 if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
340 // Build up the specification which indicates what DDLs
341 // contributed to the output data.
342 specification |= blocks[n].fSpecification;
344 AliHLTMUONMansoTracksBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
345 if (not inblock.BufferSizeOk())
347 size_t headerSize = sizeof(AliHLTMUONMansoTracksBlockReader::HeaderType);
348 if (blocks[n].fSize < headerSize)
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
358 size_t expectedWidth = sizeof(AliHLTMUONMansoTracksBlockReader::ElementType);
359 if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
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
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()
377 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
379 int result = AddTrack(&inblock[i]);
382 size = 0; // Important to tell framework that nothing was generated.
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
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
402 // Now we can create our two new output data blocks for the single tracks
404 AliHLTMUONSinglesDecisionBlockWriter singlesBlock(outputPtr, size);
406 if (not singlesBlock.InitCommonHeader())
408 Logging(kHLTLogError,
409 "AliHLTMUONDecisionComponent::DoEvent",
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)
415 size = 0; // Important to tell framework that nothing was generated.
419 if (not singlesBlock.SetNumberOfEntries(fTrackCount))
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.",
427 size = 0; // Important to tell framework that nothing was generated.
431 AliHLTMUONPairsDecisionBlockWriter pairsBlock(
432 outputPtr + singlesBlock.BytesUsed(),
433 size - singlesBlock.BytesUsed()
436 if (not pairsBlock.InitCommonHeader())
438 Logging(kHLTLogError,
439 "AliHLTMUONDecisionComponent::DoEvent",
441 "The buffer is only %d bytes in size. We need a minimum of"
442 " %d bytes for the pairs output data block.",
444 sizeof(AliHLTMUONPairsDecisionBlockWriter::HeaderType) + singlesBlock.BytesUsed()
446 size = 0; // Important to tell framework that nothing was generated.
450 AliHLTUInt32_t numOfPairs = fTrackCount * (fTrackCount-1) / 2;
451 if (not pairsBlock.SetNumberOfEntries(numOfPairs))
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.",
460 size = 0; // Important to tell framework that nothing was generated.
464 ApplyTriggerAlgorithm(
465 singlesBlock.BlockHeader(),
466 singlesBlock.GetArray(),
467 pairsBlock.BlockHeader(),
468 pairsBlock.GetArray()
471 AliHLTComponentBlockData sbd;
473 sbd.fPtr = outputPtr;
475 sbd.fSize = singlesBlock.BytesUsed();
476 sbd.fDataType = AliHLTMUONConstants::SinglesDecisionBlockDataType();
477 sbd.fSpecification = specification;
478 outputBlocks.push_back(sbd);
479 size = singlesBlock.BytesUsed();
481 AliHLTComponentBlockData 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();
495 int AliHLTMUONDecisionComponent::ReadConfigFromCDB(
497 bool setLowPtCut, bool setHighPtCut,
498 bool setLowMassCut, bool setHighMassCut
501 /// Reads the cut parameters from the CDB.
503 assert(AliCDBManager::Instance() != NULL);
505 const char* pathToEntry = AliHLTMUONConstants::DecisionComponentCDBPath();
509 AliCDBEntry* entry = AliCDBManager::Instance()->Get(pathToEntry);
512 HLTError("Could not get the CDB entry for \"%s\".", pathToEntry);
516 TObject* obj = entry->GetObject();
519 HLTError("Configuration object for \"%s\" is missing.", pathToEntry);
523 if (obj->IsA() != TMap::Class())
525 HLTError("Wrong type for configuration object in \"%s\". Found a %s but we need a TMap.",
526 pathToEntry, obj->ClassName()
530 TMap* map = dynamic_cast<TMap*>(obj);
534 TPair* pair = static_cast<TPair*>(map->FindObject("lowptcut"));
537 HLTError("Configuration object for \"%s\" does not contain the low pT cut value.",
542 TObject* valueObj = pair->Value();
543 if (valueObj->IsA() != TObjString::Class())
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()
551 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
552 if (not value.IsFloat())
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()
560 fLowPtCut = (AliHLTFloat32_t) value.Atof();
565 TPair* pair = static_cast<TPair*>(map->FindObject("highptcut"));
568 HLTError("Configuration object for \"%s\" does not contain the high pT cut value.",
573 TObject* valueObj = pair->Value();
574 if (valueObj->IsA() != TObjString::Class())
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()
582 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
583 if (not value.IsFloat())
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()
591 fHighPtCut = (AliHLTFloat32_t) value.Atof();
596 TPair* pair = static_cast<TPair*>(map->FindObject("lowmasscut"));
599 HLTError("Configuration object for \"%s\" does not contain the low invariant mass cut value.",
604 TObject* valueObj = pair->Value();
605 if (valueObj->IsA() != TObjString::Class())
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()
613 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
614 if (not value.IsFloat())
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()
622 fLowMassCut = (AliHLTFloat32_t) value.Atof();
627 TPair* pair = static_cast<TPair*>(map->FindObject("highmasscut"));
630 HLTError("Configuration object for \"%s\" does not contain the high invariant mass cut value.",
635 TObject* valueObj = pair->Value();
636 if (valueObj->IsA() != TObjString::Class())
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()
644 TString value = dynamic_cast<TObjString*>(valueObj)->GetString();
645 if (not value.IsFloat())
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()
653 fHighMassCut = (AliHLTFloat32_t) value.Atof();
660 int AliHLTMUONDecisionComponent::AddTrack(const AliHLTMUONMansoTrackStruct* track)
662 /// Adds a track to the internal track list for future reference in
663 /// ApplyTriggerAlgorithm when we actually apply the trigger algorithm.
665 assert(fTrackCount <= fMaxTracks);
666 assert(fTracks != NULL);
668 if (fTrackCount == fMaxTracks)
670 // Buffer full so we need to resize it.
671 const AliHLTMUONMansoTrackStruct** tmp = NULL;
674 tmp = new AliHLTMUONMansoTrackStructP[fMaxTracks+1];
676 catch (const std::bad_alloc&)
678 HLTError("Could not allocate more memory for the track array.");
682 // Copy over the exisiting data and then delete the old array.
683 memcpy(tmp, fTracks, sizeof(AliHLTMUONMansoTrackStructP)*fTrackCount);
686 fMaxTracks = fMaxTracks+1;
689 fTracks[fTrackCount] = track;
695 void AliHLTMUONDecisionComponent::ApplyTriggerAlgorithm(
696 AliHLTMUONSinglesDecisionBlockStruct& singlesHeader,
697 AliHLTMUONTrackDecisionStruct* singlesDecision,
698 AliHLTMUONPairsDecisionBlockStruct& pairsHeader,
699 AliHLTMUONPairDecisionStruct* pairsDecision
702 /// This method applies the dHLT trigger decision algorithm to all the
703 /// tracks found in the input data.
705 // Zero the trigger counters for single tracks.
706 singlesHeader.fNlowPt = 0;
707 singlesHeader.fNhighPt = 0;
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;
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++)
725 const AliHLTMUONMansoTrackStruct* track = fTracks[n];
726 AliHLTMUONTrackDecisionStruct& decision = singlesDecision[n];
728 bool passedHighPtCut = false;
729 bool passedLowPtCut = false;
731 AliHLTFloat32_t pt = sqrt(track->fPx * track->fPx + track->fPy * track->fPy);
735 passedHighPtCut = true;
736 singlesHeader.fNlowPt++;
740 passedLowPtCut = true;
741 singlesHeader.fNhighPt++;
744 decision.fTrackId = track->fId;
745 decision.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(
746 passedHighPtCut, passedLowPtCut
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++)
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];
765 AliHLTFloat32_t muMass = 0.1056583568; // muon mass in GeV/c^2
767 AliHLTFloat32_t mass = AliHLTMUONCalculations::ComputeMass(
768 muMass, tracki->fPx, tracki->fPy, tracki->fPz,
769 muMass, trackj->fPx, trackj->fPy, trackj->fPz
772 AliHLTMUONParticleSign signi, signj;
774 AliHLTMUONUtils::UnpackMansoTrackFlags(tracki->fFlags, signi, hitset);
775 AliHLTMUONUtils::UnpackMansoTrackFlags(trackj->fFlags, signj, hitset);
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++;
784 bool unlikeSign = (signi == kSignMinus and signj == kSignPlus) or
785 (signi == kSignPlus and signj == kSignMinus);
787 bool passedHighMassCut = false;
788 bool passedLowMassCut = false;
791 pairsHeader.fNunlikeAnyPt++;
792 if (lowPtCount == 2) pairsHeader.fNunlikeLowPt++;
793 if (highPtCount == 2) pairsHeader.fNunlikeHighPt++;
795 if (mass > fHighMassCut)
797 passedHighMassCut = true;
798 if (highPtCount == 2) pairsHeader.fNmassHigh++;
800 if (mass > fLowMassCut)
802 passedLowMassCut = true;
803 pairsHeader.fNmassAny++;
804 if (lowPtCount == 2) pairsHeader.fNmassLow++;
809 pairsHeader.fNlikeAnyPt++;
810 if (lowPtCount == 2) pairsHeader.fNlikeLowPt++;
811 if (highPtCount == 2) pairsHeader.fNlikeHighPt++;
814 decision.fTrackAId = tracki->fId;
815 decision.fTrackBId = trackj->fId;
816 decision.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(
817 passedHighMassCut, passedLowMassCut, unlikeSign,
818 highPtCount, lowPtCount
820 decision.fInvMass = mass;
825 assert( currentPair == fTrackCount * (fTrackCount-1) / 2 );