2 /**************************************************************************
3 * This file is property of and copyright by the ALICE HLT Project *
4 * All rights reserved. *
7 * Artur Szostak <artursz@iafrica.com> *
9 * Permission to use, copy, modify and distribute this software and its *
10 * documentation strictly for non-commercial purposes is hereby granted *
11 * without fee, provided that the above copyright notice appears in all *
12 * copies and that both the copyright notice and this permission notice *
13 * appear in the supporting documentation. The authors make no claims *
14 * about the suitability of this software for any purpose. It is *
15 * provided "as is" without express or implied warranty. *
16 **************************************************************************/
18 /// @file AliHLTMuonSpectroTriggerComponent.cxx
19 /// @author Artur Szostak <artursz@iafrica.com>
21 /// @brief Implementation of the muon spectrometer trigger component.
23 /// The AliHLTMuonSpectroTriggerComponent component is used to generate the HLT
24 /// trigger for the muon spectrometer.
26 #include "AliHLTMuonSpectroTriggerComponent.h"
27 #include "AliHLTTriggerDecision.h"
28 #include "AliHLTMuonSpectroScalars.h"
29 #include "AliHLTMUONDataBlockReader.h"
30 #include "AliHLTMUONConstants.h"
31 #include "AliHLTMUONUtils.h"
32 #include "AliMUONTriggerDDLDecoderEventHandler.h"
34 ClassImp(AliHLTMuonSpectroTriggerComponent);
37 AliHLTMuonSpectroTriggerComponent::AliHLTMuonSpectroTriggerComponent() :
39 fBufferSizeConst(1024*16),
40 fBufferSizeMultiplier(1),
44 fTriggerTrigRecs(false),
48 // Default constructor.
52 AliHLTMuonSpectroTriggerComponent::~AliHLTMuonSpectroTriggerComponent()
54 // Default destructor.
58 void AliHLTMuonSpectroTriggerComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list) const
60 // Returns the list of input types expected.
61 list.push_back(AliHLTMUONConstants::DDLRawDataType());
62 list.push_back(AliHLTMUONConstants::TriggerRecordsBlockDataType());
63 list.push_back(AliHLTMUONConstants::RecHitsBlockDataType());
64 list.push_back(AliHLTMUONConstants::MansoTracksBlockDataType());
65 list.push_back(AliHLTMUONConstants::SinglesDecisionBlockDataType());
66 list.push_back(AliHLTMUONConstants::PairsDecisionBlockDataType());
70 void AliHLTMuonSpectroTriggerComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list) const
72 // Return the output data types generated.
74 list.push_back(kAliHLTDataTypeTriggerDecision);
75 list.push_back(kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT);
79 void AliHLTMuonSpectroTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
81 // Returns the output data size estimate.
83 constBase = fBufferSizeConst;
84 inputMultiplier = fBufferSizeMultiplier;
88 AliHLTComponent* AliHLTMuonSpectroTriggerComponent::Spawn()
90 // Creates and returns a new instance.
92 return new AliHLTMuonSpectroTriggerComponent;
96 Int_t AliHLTMuonSpectroTriggerComponent::DoInit(int argc, const char** argv)
98 // Initialise the component.
101 fTriggerDDLs = false;
102 fTriggerHits = false;
103 fTriggerTrigRecs = false;
104 fTriggerTracks = false;
105 fTriggerDimuons = false;
107 for (int i = 0; i < argc; i++)
109 if (strcmp(argv[i], "-makestats") == 0)
114 if (strcmp(argv[i], "-triggerddls") == 0)
119 if (strcmp(argv[i], "-triggerhits") == 0)
124 if (strcmp(argv[i], "-triggertrigrecs") == 0)
126 fTriggerTrigRecs = true;
129 if (strcmp(argv[i], "-triggertracks") == 0)
131 fTriggerTracks = true;
134 if (strcmp(argv[i], "-triggerdimuons") == 0)
136 fTriggerDimuons = true;
139 if (strcmp(argv[i], "-triggerany") == 0)
142 fTriggerTrigRecs = true;
143 fTriggerTracks = true;
144 fTriggerDimuons = true;
148 HLTError("Unknown option '%s'.", argv[i]);
152 // If nothing was turned on to trigger then turn everything on by default.
153 if (fTriggerHits == false and fTriggerTrigRecs == false
154 and fTriggerTracks == false and fTriggerDimuons == false
157 fTriggerTracks = true;
158 fTriggerDimuons = true;
165 Int_t AliHLTMuonSpectroTriggerComponent::DoDeinit()
167 // Cleans up the component.
173 int AliHLTMuonSpectroTriggerComponent::DoTrigger()
175 // Applies the trigger for the HLT.
179 bool gotddls = false;
180 bool gothits = false;
181 bool gottrigrecs = false;
182 bool gottracks = false;
183 bool gotsingles = false;
184 bool gotpairs = false;
189 UInt_t nhitsCh[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
190 UInt_t ntrigrecs = 0;
193 UInt_t ntracksMT = 0; // from Manso track blocks.
194 UInt_t ntracksSD = 0; // from singles decision blocks
203 UInt_t nlikehigh = 0;
204 UInt_t nunlikeany = 0;
205 UInt_t nunlikelow = 0;
206 UInt_t nunlikehigh = 0;
208 UInt_t nhighmass = 0;
209 Double_t minmass = -1;
210 Double_t maxmass = -1;
213 AliHLTComponentDataType blockType = AliHLTMUONConstants::DDLRawDataType();
214 for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType);
216 block = GetNextInputBlock()
223 blockType = AliHLTMUONConstants::TriggerRecordsBlockDataType();
224 for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType);
226 block = GetNextInputBlock()
229 AliHLTMUONTriggerRecordsBlockReader trigRecsBlock(block->fPtr, block->fSize);
230 if (not IsBlockOk(trigRecsBlock, blockType))
232 HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str());
237 ntrigrecs += trigRecsBlock.Nentries();
238 for (AliHLTUInt32_t i = 0; i < trigRecsBlock.Nentries(); ++i)
240 AliHLTMUONParticleSign sign;
242 AliHLTMUONUtils::UnpackTriggerRecordFlags(trigRecsBlock[i].fFlags, sign, hitset);
245 case kSignPlus: ++nL0plus; break;
246 case kSignMinus: ++nL0minus; break;
249 for (int j = 0; j < 4; ++j)
261 blockType = AliHLTMUONConstants::RecHitsBlockDataType();
262 for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType);
264 block = GetNextInputBlock()
267 AliHLTMUONRecHitsBlockReader hitsBlock(block->fPtr, block->fSize);
268 if (not IsBlockOk(hitsBlock, blockType))
270 HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str());
275 nhits += hitsBlock.Nentries();
276 nhitsMCH += hitsBlock.Nentries();
277 for (AliHLTUInt32_t i = 0; i < hitsBlock.Nentries(); ++i)
279 AliHLTUInt8_t chamber;
280 AliHLTUInt16_t detElemId;
281 AliHLTMUONUtils::UnpackRecHitFlags(hitsBlock[i].fFlags, chamber, detElemId);
288 HLTWarning("Received a reconstructed hit which indicates"
289 " an invalid chamber number of %d. The expected"
290 " range is [0..9]. The data blockis probably corrupt.",
297 blockType = AliHLTMUONConstants::MansoTracksBlockDataType();
298 for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType);
300 block = GetNextInputBlock()
303 AliHLTMUONMansoTracksBlockReader tracksBlock(block->fPtr, block->fSize);
304 if (not IsBlockOk(tracksBlock, blockType))
306 HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str());
311 ntracksMT += tracksBlock.Nentries();
312 for (AliHLTUInt32_t i = 0; i < tracksBlock.Nentries(); ++i)
314 AliHLTMUONParticleSign sign;
316 AliHLTMUONUtils::UnpackMansoTrackFlags(tracksBlock[i].fFlags, sign, hitset);
319 case kSignPlus: ++nplus; break;
320 case kSignMinus: ++nminus; break;
326 blockType = AliHLTMUONConstants::SinglesDecisionBlockDataType();
327 for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType);
329 block = GetNextInputBlock()
332 AliHLTMUONSinglesDecisionBlockReader singlesBlock(block->fPtr, block->fSize);
333 if (not IsBlockOk(singlesBlock, blockType))
335 HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str());
340 ntracksSD += singlesBlock.Nentries();
341 nlowpt += singlesBlock.BlockHeader().fNlowPt;
342 nhighpt += singlesBlock.BlockHeader().fNhighPt;
343 for (AliHLTUInt32_t i = 0; i < singlesBlock.Nentries(); ++i)
345 if (singlesBlock[i].fPt < minpt or minpt == -1) minpt = singlesBlock[i].fPt;
346 if (singlesBlock[i].fPt > maxpt or maxpt == -1) maxpt = singlesBlock[i].fPt;
350 blockType = AliHLTMUONConstants::PairsDecisionBlockDataType();
351 for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType);
353 block = GetNextInputBlock()
356 AliHLTMUONPairsDecisionBlockReader pairsBlock(block->fPtr, block->fSize);
357 if (not IsBlockOk(pairsBlock, blockType))
359 HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str());
364 nunlikeany += pairsBlock.BlockHeader().fNunlikeAnyPt;
365 nlikeany += pairsBlock.BlockHeader().fNlikeAnyPt;
366 // Dont use the other scalars from the pair decisions block header because
367 // they are much more restrictive. They count pairs where both tracks pass
368 // the low or high pT cut. But we want to relax this to just one track needs
369 // to pass the pT cut.
370 for (AliHLTUInt32_t i = 0; i < pairsBlock.Nentries(); ++i)
372 if (pairsBlock[i].fInvMass < minmass or minmass == -1) minmass = pairsBlock[i].fInvMass;
373 if (pairsBlock[i].fInvMass > maxmass or maxmass == -1) maxmass = pairsBlock[i].fInvMass;
374 bool highMass, lowMass, unlike;
375 AliHLTUInt8_t highPtCount, lowPtCount;
376 AliHLTMUONUtils::UnpackPairDecisionBits(
377 pairsBlock[i].fTriggerBits, highMass, lowMass, unlike,
378 highPtCount, lowPtCount
382 if (lowPtCount >= 1) ++nunlikelow;
383 if (highPtCount >= 1) ++nunlikehigh;
384 if (lowMass) ++nlowmass;
385 if (highMass) ++nhighmass;
389 if (lowPtCount >= 1) ++nlikelow;
390 if (highPtCount >= 1) ++nlikehigh;
395 // Select the largest value for nTracks since we might only get this information
396 // from singles decision blocks.
397 UInt_t ntracks = ntracksSD > ntracksMT ? ntracksSD : ntracksMT;
399 bool triggeredOnDDLs = fTriggerDDLs and nL0 > 0;
400 bool triggeredOnHits = fTriggerHits and nhitsMCH > 0;
401 bool triggeredOnTrigRecs = fTriggerTrigRecs and ntrigrecs > 0;
402 bool triggeredOnTracks = fTriggerTracks and ntracks > 0;
403 bool triggeredOnDimuons = fTriggerDimuons and (nunlikeany > 0
404 or nunlikelow > 0 or nunlikehigh > 0 or nlowmass > 0 or nhighmass > 0);
406 if (triggeredOnDimuons)
408 SetDescription("Dimuon in muon spectrometer");
409 SetTriggerDomain(AliHLTTriggerDomain("*******:MUON"));
411 else if (triggeredOnTracks)
413 SetDescription("Tracks in muon spectrometer");
414 SetTriggerDomain(AliHLTTriggerDomain("*******:MUON"));
416 else if (triggeredOnTrigRecs)
418 SetDescription("Muon trigger chambers triggered");
421 SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRG | AliHLTReadoutList::kMUONTRK));
422 SetTriggerDomain(AliHLTTriggerDomain("TRIGRECS:MUON,RECHITS :MUON"));
426 SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRG));
427 SetTriggerDomain(AliHLTTriggerDomain("TRIGRECS:MUON"));
430 else if (triggeredOnHits)
432 SetDescription("Hits in muon tracking chambers");
433 SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRK));
434 SetTriggerDomain(AliHLTTriggerDomain("RECHITS :MUON"));
436 else if (triggeredOnDDLs)
438 SetDescription("DDL in muon tracking chambers");
439 SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRG | AliHLTReadoutList::kMUONTRK));
440 SetTriggerDomain(AliHLTTriggerDomain("DDL_RAW :MUON"));
444 SetDescription("Not triggered");
445 SetTriggerDomain(AliHLTTriggerDomain());
448 if (triggeredOnDimuons or triggeredOnTracks or triggeredOnTrigRecs or triggeredOnHits or triggeredOnDDLs)
450 result = TriggerEvent();
451 if (result == -ENOSPC) goto increaseBuffer;
452 if (result != 0) return result;
457 AliHLTMuonSpectroScalars scalars;
458 if (gotddls) scalars.Add("NL0", "Number of L0 triggered event", nL0);
459 if (gothits and gottrigrecs) scalars.Add("NHits", "Total number of hits", nhits);
460 if (gottrigrecs) scalars.Add("NHitsMTR", "Number of hits in trigger chambers", nhitsMTR);
463 scalars.Add("NHitsMCH", "Number of hits in tracking chambers", nhitsMCH);
464 for (int i = 0; i < 10; i++)
466 scalars.Add(Form("NHitsCh%d", i+1), Form("Number of hits in chamber %d", i+1), nhitsCh[i]);
471 for (int i = 10; i < 14; i++)
473 scalars.Add(Form("NHitsCh%d", i+1), Form("Number of hits in chamber %d", i+1), nhitsCh[i]);
475 scalars.Add("NTrigRecs", "Total number of trigger records", ntrigrecs);
476 scalars.Add("NL0+", "Number of positive sign tracks in L0", nL0plus);
477 scalars.Add("NL0-", "Number of negative sign tracks in L0", nL0minus);
479 if (gottracks or gotsingles) scalars.Add("NTracks", "Total number of tracks", ntracks);
482 scalars.Add("N+", "Number of positive sign tracks", nplus);
483 scalars.Add("N-", "Number of negative sign tracks", nminus);
487 scalars.Add("NLowPt", "Number of low pT tracks", nlowpt);
488 scalars.Add("NHighPt", "Number of high pT tracks", nhighpt);
489 scalars.Add("MinPt", "Minimum pT found (GeV/c)", minpt);
490 scalars.Add("MaxPt", "Maximum pT found (GeV/c)", maxpt);
494 scalars.Add("NLikeAny", "Number of like sign track pairs", nlikeany);
495 scalars.Add("NLikeLow", "Number of like sign pairs with at least 1 low pT track.", nlikelow);
496 scalars.Add("NLikeHigh", "Number of like sign pairs with at least 1 high pT track.", nlikehigh);
497 scalars.Add("NUnlikeAny", "Number of unlike sign track pairs", nunlikeany);
498 scalars.Add("NUnlikeLow", "Number of unlike sign pairs with at least 1 low pT track.", nunlikelow);
499 scalars.Add("NUnlikeHigh", "Number of unlike sign pairs with at least 1 high pT track.", nunlikehigh);
500 scalars.Add("NLowMass", "Number of low mass dimuons", nlowmass);
501 scalars.Add("NHighMass", "Number of high mass dimuons", nhighmass);
502 scalars.Add("MinMass", "Minimum invariant mass found for dimuon (GeV/c^2)", minmass);
503 scalars.Add("MaxMass", "Maximum invariant mass found for dimuon (GeV/c^2)", maxmass);
506 result = PushBack(&scalars, kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT);
507 if (result == -ENOSPC) goto increaseBuffer;
512 // Increase the estimated buffer space required since the PushBack
513 // or TriggerEvent methods indicate that they ran out of buffer space.
514 fBufferSizeConst += 1024*1024;
515 fBufferSizeMultiplier *= 2.;
520 template <typename BlockReader>
521 bool AliHLTMuonSpectroTriggerComponent::IsBlockOk(
522 const BlockReader& reader, const AliHLTComponentDataType& type
525 // Method for checking the block structure.
527 if (not reader.BufferSizeOk())
529 string name = DataType2Text(type).c_str();
530 size_t headerSize = sizeof(typename BlockReader::HeaderType);
531 if (reader.BufferSize() < headerSize)
533 HLTError("Received a '%s' data block with a size of %d bytes,"
534 " which is smaller than the minimum valid size of %d bytes."
535 " The block must be corrupt.",
536 name.c_str(), reader.BufferSize(), headerSize
540 size_t expectedWidth = sizeof(typename BlockReader::ElementType);
541 if (reader.CommonBlockHeader().fRecordWidth != expectedWidth)
543 HLTError("Received a '%s' data block with a record"
544 " width of %d bytes, but the expected value is %d bytes."
545 " The block might be corrupt.",
547 reader.CommonBlockHeader().fRecordWidth,
552 HLTError("Received a '%s' data block with a size of %d bytes,"
553 " but the block header claims the block should be %d bytes."
554 " The block might be corrupt.",
555 name.c_str(), reader.BufferSize(), reader.BytesUsed()