From c1550d2c99f9c2daeb5505008cd59977c9c7ab68 Mon Sep 17 00:00:00 2001 From: aszostak Date: Fri, 13 Nov 2009 12:11:01 +0000 Subject: [PATCH] Adding HLT trigger component for the muon spectrometer to fit within the HLT trigger framework. --- HLT/CMake_libAliHLTTrigger.txt | 2 + HLT/libAliHLTTrigger.pkg | 12 +- HLT/trigger/AliHLTMuonSpectroScalars.cxx | 387 +++++++++++++ HLT/trigger/AliHLTMuonSpectroScalars.h | 288 ++++++++++ .../AliHLTMuonSpectroTriggerComponent.cxx | 533 ++++++++++++++++++ .../AliHLTMuonSpectroTriggerComponent.h | 188 ++++++ HLT/trigger/AliHLTTriggerAgent.cxx | 28 +- HLT/trigger/AliHLTTriggerLinkDef.h | 3 + HLT/trigger/CreateTriggerMenuCDBEntry.C | 4 + HLT/trigger/test/Makefile.am | 10 +- HLT/trigger/test/testMuonSpectroTrigger.C | 420 ++++++++++++++ .../Run0_999999999_v0_s2.root | Bin 0 -> 4599 bytes 12 files changed, 1868 insertions(+), 7 deletions(-) create mode 100644 HLT/trigger/AliHLTMuonSpectroScalars.cxx create mode 100644 HLT/trigger/AliHLTMuonSpectroScalars.h create mode 100644 HLT/trigger/AliHLTMuonSpectroTriggerComponent.cxx create mode 100644 HLT/trigger/AliHLTMuonSpectroTriggerComponent.h create mode 100644 HLT/trigger/test/testMuonSpectroTrigger.C create mode 100644 OCDB/HLT/ConfigHLT/HLTGlobalTrigger/Run0_999999999_v0_s2.root diff --git a/HLT/CMake_libAliHLTTrigger.txt b/HLT/CMake_libAliHLTTrigger.txt index f65d3208e26..e4cf0dc0a0f 100644 --- a/HLT/CMake_libAliHLTTrigger.txt +++ b/HLT/CMake_libAliHLTTrigger.txt @@ -17,6 +17,8 @@ trigger/AliHLTTriggerSelectiveReadoutComponent.cxx trigger/AliHLTTriggerMonitoringComponent.cxx trigger/AliHLTTriggerPhosClusterEnergy.cxx trigger/AliHLTTriggerPhosMip.cxx +trigger/AliHLTMuonSpectroScalars.cxx +trigger/AliHLTMuonSpectroTriggerComponent.cxx ) # fill list of header files from list of source files diff --git a/HLT/libAliHLTTrigger.pkg b/HLT/libAliHLTTrigger.pkg index 5e26cc32c5c..c01f789547f 100644 --- a/HLT/libAliHLTTrigger.pkg +++ b/HLT/libAliHLTTrigger.pkg @@ -15,9 +15,9 @@ CLASS_HDRS:= \ AliHLTGlobalTriggerConfig.h \ AliHLTGlobalTriggerComponent.h \ AliHLTTriggerBarrelMultiplicity.h \ - AliHLTD0Trigger.h \ - AliHLTD0toKpi.h \ - AliHLTTriggerITSMultiplicity.h \ + AliHLTD0Trigger.h \ + AliHLTD0toKpi.h \ + AliHLTTriggerITSMultiplicity.h \ AliHLTTriggerBarrelCosmic.h \ AliHLTTriggerAgent.h \ AliHLTEventSummary.h \ @@ -33,7 +33,9 @@ CLASS_HDRS:= \ AliHLTTriggerDetectorGeom.h \ AliHLTTriggerDetectorGeomRectangle.h \ AliHLTTriggerDecisionParameters.h \ - AliHLTTriggerGammaConversion.h + AliHLTTriggerGammaConversion.h \ + AliHLTMuonSpectroScalars.h \ + AliHLTMuonSpectroTriggerComponent.h # library sources MODULE_SRCS:= $(CLASS_HDRS:.h=.cxx) @@ -55,7 +57,7 @@ MODULE_HDRS:= $(CLASS_HDRS) # enable automatic generation. MODULE_DHDR:= AliHLTTriggerLinkDef.h -EINCLUDE := HLT/BASE HLT/BASE/util HLT/trigger HLT/TPCLib HLT/TRD TRD HLT/ITS +EINCLUDE := HLT/BASE HLT/BASE/util HLT/trigger HLT/TPCLib HLT/TRD TRD HLT/ITS HLT/MUON MUON LIBRARY_DEP := -lHLTbase diff --git a/HLT/trigger/AliHLTMuonSpectroScalars.cxx b/HLT/trigger/AliHLTMuonSpectroScalars.cxx new file mode 100644 index 00000000000..208625fbfe6 --- /dev/null +++ b/HLT/trigger/AliHLTMuonSpectroScalars.cxx @@ -0,0 +1,387 @@ +// $Id: $ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * All rights reserved. * + * * + * Primary Authors: * + * Artur Szostak * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/// @file AliHLTMuonSpectroScalars.cxx +/// @author Artur Szostak +/// @date 9 Nov 2009 +/// @brief Implementation of the muon spectrometer trigger scalars. +/// +/// This implements the trigger scalars for the muon spectrometer that can be used +/// in the HLT global trigger and/or added to the AliHLTEventSummary. + +#include "AliHLTMuonSpectroScalars.h" +#include "AliLog.h" +#include "TObjArray.h" +#include "TObjString.h" +#include "TString.h" +#include "Riostream.h" + +ClassImp(AliHLTMuonSpectroScalars); +ClassImp(AliHLTMuonSpectroScalars::AliScalar); + + +AliHLTMuonSpectroScalars::AliHLTMuonSpectroScalars() : + TObject(), + fScalars(AliHLTMuonSpectroScalars::AliScalar::Class(), 128), + fIndex(128), + fIndexValid(false) +{ + // Default constructor. + + fIndex.SetOwner(kFALSE); +} + + +AliHLTMuonSpectroScalars::AliHLTMuonSpectroScalars(const AliHLTMuonSpectroScalars& obj) : + TObject(obj), + fScalars(obj.fScalars), + fIndex(obj.fIndex), + fIndexValid(obj.fIndexValid) +{ + // Copy constructor performs a deep copy. + + fIndex.SetOwner(kFALSE); +} + + +AliHLTMuonSpectroScalars::~AliHLTMuonSpectroScalars() +{ + // Default destructor. + + Clear(); +} + + +void AliHLTMuonSpectroScalars::Add(const char* name, const char* description, Double_t value) +{ + // Adds a new scalar. + + new (fScalars[fScalars.GetEntriesFast()]) AliScalar(value, name, description); + fIndexValid = false; // Invalidate the index. +} + + +bool AliHLTMuonSpectroScalars::Exists(const char* name) const +{ + // Checks if the scalar exists or not. + + if (not fIndexValid) MakeIndex(); + AliScalar tmpobj(0, name, ""); + Int_t n = fIndex.BinarySearch(&tmpobj); + if (n == -1) return false; + return true; +} + + +AliHLTMuonSpectroScalars::AliScalar* AliHLTMuonSpectroScalars::GetScalarN(UInt_t n) +{ + // Fetch the n'th scalar object. + + if (n >= NumberOfScalars()) + { + AliError(Form("Value 'n' is out of bounds. Should be in the range [0..%d].", NumberOfScalars()-1)); + return NULL; + } + return static_cast( fScalars.UncheckedAt(Int_t(n)) ); +} + + +const AliHLTMuonSpectroScalars::AliScalar* AliHLTMuonSpectroScalars::GetScalarN(UInt_t n) const +{ + // Fetch the n'th scalar object. + + if (n >= NumberOfScalars()) + { + AliError(Form("Value 'n' is out of bounds. Should be in the range [0..%d].", NumberOfScalars()-1)); + return NULL; + } + return static_cast( fScalars.UncheckedAt(Int_t(n)) ); +} + + +AliHLTMuonSpectroScalars::AliScalar* AliHLTMuonSpectroScalars::GetScalar(const char* name) +{ + // Fetch the named scalar object. + + if (not fIndexValid) MakeIndex(); + AliScalar tmpobj(0, name, ""); + Int_t n = fIndex.BinarySearch(&tmpobj); + if (n == -1) + { + AliError(Form("Scalar '%s' could not be found.", name)); + return NULL; + } + return static_cast( fIndex.UncheckedAt(n) ); +} + + +const AliHLTMuonSpectroScalars::AliScalar* AliHLTMuonSpectroScalars::GetScalar(const char* name) const +{ + // Fetch the named scalar object. + + if (not fIndexValid) MakeIndex(); + AliScalar tmpobj(0, name, ""); + Int_t n = fIndex.BinarySearch(&tmpobj); + if (n == -1) + { + AliError(Form("Scalar '%s' could not be found.", name)); + return NULL; + } + return static_cast( fIndex.UncheckedAt(n) ); +} + + +Double_t AliHLTMuonSpectroScalars::GetN(UInt_t n) const +{ + // Fetches the n'th scalar value. + + const AliScalar* scalar = GetScalarN(n); + if (scalar == NULL) return 0; + return scalar->Value(); +} + + +Double_t AliHLTMuonSpectroScalars::Get(const char* name) const +{ + // Fetches the n'th scalar value. + + const AliScalar* scalar = GetScalar(name); + if (scalar == NULL) return 0; + return scalar->Value(); +} + + +bool AliHLTMuonSpectroScalars::SetN(UInt_t n, Double_t value) +{ + // Sets the n'th scalar value. + + AliScalar* scalar = GetScalarN(n); + if (scalar == NULL) return false; + scalar->Value(value); + return true; +} + + +bool AliHLTMuonSpectroScalars::Set(const char* name, Double_t value) +{ + // Sets the named scalar value. + + AliScalar* scalar = GetScalar(name); + if (scalar == NULL) return false; + scalar->Value(value); + return true; +} + + +bool AliHLTMuonSpectroScalars::IncrementN(UInt_t n, UInt_t count) +{ + // Increments the n'th scalar by a value of 'count'. + + AliScalar* scalar = GetScalarN(n); + if (scalar == NULL) return false; + scalar->Increment(count); + return true; +} + + +bool AliHLTMuonSpectroScalars::Increment(const char* name, UInt_t count) +{ + // Increments the named scalar by a value of 'count'. + + AliScalar* scalar = GetScalar(name); + if (scalar == NULL) return false; + scalar->Increment(count); + return true; +} + + +const char* AliHLTMuonSpectroScalars::Name(UInt_t n) const +{ + // Fetches the n'th scalar's name. + + const AliScalar* scalar = GetScalarN(n); + if (scalar == NULL) return NULL; + return scalar->Name(); +} + + +const char* AliHLTMuonSpectroScalars::Description(UInt_t n) const +{ + // Fetches the n'th scalar's description. + + const AliScalar* scalar = GetScalarN(n); + if (scalar == NULL) return NULL; + return scalar->Description(); +} + + +void AliHLTMuonSpectroScalars::Reset() +{ + // Sets all the scalar values to zero. + + for (Int_t i = 0; i < fScalars.GetEntriesFast(); ++i) + { + AliScalar* scalar = static_cast( fScalars.UncheckedAt(i) ); + scalar->Value(0); + } +} + + +void AliHLTMuonSpectroScalars::Clear(Option_t* option) +{ + // Clears the array of scalars. + + fScalars.Delete(option); + fIndex.Clear(); +} + + +void AliHLTMuonSpectroScalars::Copy(TObject& object) const +{ + // Performs a deep copy. + + if (object.IsA() != AliHLTMuonSpectroScalars::Class()) + { + AliError(Form("Cannot copy to an object of type '%s'.", object.ClassName())); + return; + } + AliHLTMuonSpectroScalars* obj = static_cast(&object); + *obj = *this; +} + + +TObject* AliHLTMuonSpectroScalars::FindObject(const char* name) const +{ + // Finds the scalar object by name. + + if (fIndexValid) + { + AliScalar tmpobj(0, name, ""); + Int_t n = fIndex.BinarySearch(&tmpobj); + if (n != -1) return fIndex.UncheckedAt(n); + } + else + { + return fScalars.FindObject(name); + } + return NULL; +} + + +TObject* AliHLTMuonSpectroScalars::FindObject(const TObject* obj) const +{ + // Finds the scalar object with the same name as obj->GetName(). + + return FindObject(obj->GetName()); +} + + +void AliHLTMuonSpectroScalars::Print(Option_t* option) const +{ + // Prints the muon spectrometer's HLT trigger scalars. + + TString opt = option; + if (opt == "compact") + { + if (NumberOfScalars() > 0) + cout << GetN(0); + for (UInt_t i = 1; i < NumberOfScalars(); ++i) cout << ", " << GetN(i); + cout << endl; + return; + } + + // Calculate the maximum field width required to keep things aligned. + int fieldwidth = 0; + for (Int_t i = 0; i < fScalars.GetEntriesFast(); ++i) + { + AliScalar* scalar = static_cast( fScalars.UncheckedAt(i) ); + int length = strlen(scalar->Description()); + if (length > fieldwidth) fieldwidth = length; + } + if (fieldwidth > 80) fieldwidth = 80; + + cout << "HLT muon spectrometer trigger scalars:" << endl; + for (Int_t i = 0; i < fScalars.GetEntriesFast(); ++i) + { + AliScalar* scalar = static_cast( fScalars.UncheckedAt(i) ); + cout << setw(fieldwidth) << scalar->Description() << setw(0) + << " = " << scalar->Value() << endl; + } + if (fScalars.GetEntriesFast() == 0) cout << "(none)" << endl; +} + + +AliHLTMuonSpectroScalars& AliHLTMuonSpectroScalars::operator = (const AliHLTMuonSpectroScalars& obj) +{ + // Performs a deep copy. + + if (this == &obj) return *this; + fScalars.Delete(); + for (Int_t i = 0; i < obj.fScalars.GetEntriesFast(); ++i) + { + AliScalar* scalar = static_cast( obj.fScalars.UncheckedAt(i) ); + Add(scalar->Name(), scalar->Description(), scalar->Value()); + } + MakeIndex(); + return *this; +} + + +bool AliHLTMuonSpectroScalars::operator == (const AliHLTMuonSpectroScalars& obj) const +{ + // Compares two scalar objects. + + if (not fIndexValid) MakeIndex(); + if (fScalars.GetEntriesFast() != obj.fScalars.GetEntriesFast()) return false; + for (Int_t i = 0; i < obj.fScalars.GetEntriesFast(); ++i) + { + AliScalar* scalar1 = static_cast( obj.fScalars.UncheckedAt(i) ); + Int_t n = fIndex.BinarySearch(scalar1); + if (n == -1) return false; + AliScalar* scalar2 = static_cast( fIndex.UncheckedAt(n) ); + if (scalar1->Value() != scalar2->Value()) return false; + } + return true; +} + + +void AliHLTMuonSpectroScalars::MakeIndex() const +{ + // Makes the index fIndex required for faster searching in fScalars. + + fIndex.Clear(); + for (Int_t i = 0; i < fScalars.GetEntriesFast(); ++i) + { + fIndex.Add(fScalars.UncheckedAt(i)); + } + fIndex.Sort(); + fIndexValid = true; +} + + +void AliHLTMuonSpectroScalars::AliScalar::Copy(TObject& object) const +{ + // Performs a deep copy. + + if (object.IsA() != AliHLTMuonSpectroScalars::AliScalar::Class()) + { + AliError(Form("Cannot copy to an object of type '%s'.", object.ClassName())); + return; + } + AliHLTMuonSpectroScalars::AliScalar* obj = static_cast(&object); + *obj = *this; +} diff --git a/HLT/trigger/AliHLTMuonSpectroScalars.h b/HLT/trigger/AliHLTMuonSpectroScalars.h new file mode 100644 index 00000000000..2d7de1a7cd1 --- /dev/null +++ b/HLT/trigger/AliHLTMuonSpectroScalars.h @@ -0,0 +1,288 @@ +//-*- Mode: C++ -*- +// $Id: $ +#ifndef AliHLTMUONSPECTROSCALARS_H +#define AliHLTMUONSPECTROSCALARS_H +/* This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/// @file AliHLTMuonSpectroScalars.h +/// @author Artur Szostak +/// @date 9 Nov 2009 +/// @brief Declares the scalars class for the muon spectrometer. + +#include "TObject.h" +#include "TObjArray.h" +#include "TClonesArray.h" + +/** + * @class AliHLTMuonSpectroScalars + * @brief Muon spectrometer HLT trigger summary scalars. + * + * This scalars class contains summary information such as the number of tracks found, + * number of pairs found and so on, all within the muon spectrometer. + * Objects of this class are generated by the AliHLTMuonSpectroTriggerComponent to + * be used in the HLT global trigger and/or added to the AliHLTEventSummary object. + * + * \ingroup alihlt_trigger_components + */ +class AliHLTMuonSpectroScalars : public TObject +{ +public: + /** + * Scalar class to store all the required information for a muon spectrometer scalar. + */ + class AliScalar : public TObject + { + public: + /// Default constructor + AliScalar() : TObject(), fValue(0), fName(), fDescription() {} + + /// Constructor to set some initial values. + AliScalar(Double_t value, const char* name, const char* description) : + TObject(), fValue(value), fName(name), fDescription(description) + {} + + /// Default destructor + virtual ~AliScalar() {} + + /// Inherited from TObject. Returns the name of the scalar. + virtual const char* GetName() const { return fName; } + + /// Inherited from TObject. Returns the description of the scalar. + virtual const char* GetTitle() const {return fDescription; } + + /// Inherited from TObject. Compares two scalar names. + virtual Int_t Compare(const TObject *obj) const + { + return fName.CompareTo(obj->GetName()); + } + + /// Inherited from TObject. Returns true. + virtual Bool_t IsSortable() const { return kTRUE; } + + /** + * Inherited from TObject. + * Returns true if the names of the scalars are the same. + */ + virtual Bool_t IsEqual(const TObject *obj) const + { + return fName == obj->GetName(); + } + + /// Resets the scalar value. + virtual void Clear(Option_t* /*option*/ = "") { fValue = 0; } + + /// Inherited form TObject. Performs a deep copy. + virtual void Copy(TObject& object) const; + + /// Returns the value of the scalar. + Double_t Value() const { return fValue; } + + /** + * Sets a new value for the scalar. + * \param value The new value to use. If negative then 0 is used instead. + */ + void Value(Double_t value) { fValue = value >= 0 ? value : 0; } + + /// Increments the scalar value by 'count'. + void Increment(UInt_t count = 1) { fValue += count; } + + /// Returns the name of the scalar. + const char* Name() const { return fName.Data(); } + + /// Returns the description string for the scalar. + const char* Description() const { return fDescription.Data(); } + + /// Checks if two scalar objects are equal. + bool operator == (const AliScalar& x) const + { + return fValue == x.fValue and fName == x.fName + and fDescription == x.fDescription; + } + + /// Checks if two scalar objects are not equal. + bool operator != (const AliScalar& x) const + { + return not (this->operator == (x)); + } + + private: + Double_t fValue; /// The scalar value. + TString fName; /// The name of the scalar. + TString fDescription; /// A description of what the scalar represents. + + ClassDef(AliScalar, 1); // A scalar value for the muon spectrometer. + }; + + /// Default constructor. + AliHLTMuonSpectroScalars(); + + /// The copy constructor performs a deep copy. + AliHLTMuonSpectroScalars(const AliHLTMuonSpectroScalars& obj); + + /// Default destructor. + virtual ~AliHLTMuonSpectroScalars(); + + /** + * Adds a new scalar to the end of the scalars list. + * \param name The name of the scalar value. + * \param description A short description of the scalar value. + * \param value The value of the new scalar. + */ + void Add(const char* name, const char* description, Double_t value = 0); + + /// Returns the number of scalar values. + UInt_t NumberOfScalars() const { return UInt_t(fScalars.GetEntriesFast()); } + + /// Checks to see if the named scalar exists. + bool Exists(const char* name) const; + + /** + * Fetches the n'th scalar object. + * \param n The scalar object to fetch. + * \returns the n'th scalar object, otherwise NULL if n was out of range. + */ + AliScalar* GetScalarN(UInt_t n); + const AliScalar* GetScalarN(UInt_t n) const; + + /** + * Fetches the named scalar object. Will apply a binary search for the object. + * This means rebuilding the internal index if necessary. + * \param name The name of the scalar object. + * \returns the found scalar object, otherwise NULL if it was not found. + */ + AliScalar* GetScalar(const char* name); + const AliScalar* GetScalar(const char* name) const; + + /** + * Fetches the n'th scalar value. + * \param n The scalar number to fetch. + * \returns the n'th scalar, otherwise 0 if n was out of range. + */ + Double_t GetN(UInt_t n) const; + + /** + * Fetches the a scalar value by name. + * \param name The name of the scalar. + * \returns the scalar's value, otherwise 0 if it could not be found. + */ + Double_t Get(const char* name) const; + + /** + * Sets the n'th scalar value. + * \param n The scalar number to set. + * \param value The new value for the scalar. + * \returns true if the scalar could be set, otherwise false which means + * that n was out of range. + */ + bool SetN(UInt_t n, Double_t value); + + /** + * Sets the named scalar's value. + * \param name The name of the scalar to set. + * \param value The new value for the scalar. + * \returns true if the scalar could be set, otherwise false which means + * that it was not found. + */ + bool Set(const char* name, Double_t value); + + /** + * Increments the n'th scalar by a value of 'count'. + * \param n The scalar number to increment. + * \param count The number to increment the scalar by. The default is 1. + * \returns true if the scalar could be incremented, otherwise false + * which means that n was out of range. + */ + bool IncrementN(UInt_t n, UInt_t count = 1); + + /** + * Increments the n'th scalar by a value of 'count'. + * \param name The name of the scalar to set. + * \param count The number to increment the scalar by. The default is 1. + * \returns true if the scalar could be incremented, otherwise false + * which means that it could not be found. + */ + bool Increment(const char* name, UInt_t count = 1); + + /** + * Returns the name of the n'th scalar. + * \param n The scalar number for which to return the name. + * \returns the n'th scalar's name, otherwise NULL if n was out of range. + */ + const char* Name(UInt_t n) const; + + /** + * Returns the description string for the n'th scalar. + * \param n The scalar number for which to return the description. + * \returns the n'th scalar's description, otherwise NULL if n was out of range. + */ + const char* Description(UInt_t n) const; + + /// Resets all scalar values to zero. + void Reset(); + + /** + * Removes all the scalars from the internal array. + * \param option This is passed onto the internal Delete method. + */ + virtual void Clear(Option_t* option = ""); + + /// Inherited form TObject. Performs a deep copy. + virtual void Copy(TObject& object) const; + + /// Finds the scalar object by name. Will not apply a binary search if fIndex + /// was invalidated. + virtual TObject* FindObject(const char* name) const; + + /// Finds the scalar object with the same name as obj->GetName(). + /// Will not apply a binary search if fIndex was invalidated. + virtual TObject* FindObject(const TObject* obj) const; + + /** + * Inherited from TObject, this prints the contents of this summary object. + * \param option Can be "compact", which will just print all the values on one line. + */ + virtual void Print(Option_t* option = "") const; + + /** + * The assignment operator performs a deep copy. + */ + AliHLTMuonSpectroScalars& operator = (const AliHLTMuonSpectroScalars& obj); + + /// Returns the n'th scalar value or -1 if n is out of range. + Double_t operator [] (UInt_t n) const { return GetN(n); } + + /// Returns the named scalar value or -1 if not found. + Double_t operator [] (const TString& name) const { return Get(name.Data()); } + + /** + * Comparison operator to check if two scalar objects have the same values. + * \note The description strings are not checked so they could be different + * and the order of the scalars does not matter either. + */ + bool operator == (const AliHLTMuonSpectroScalars& obj) const; + + /** + * Comparison operator to check if two scalar objects are different. + * \note The description strings are not checked, only the values + * and the order of the scalars does not matter either. + */ + bool operator != (const AliHLTMuonSpectroScalars& obj) const + { + return not (this->operator == (obj)); + } + +private: + + /// Creates the index required for faster searches of the fScalars array. + void MakeIndex() const; + + TClonesArray fScalars; /// The list of scalars. Contains AliScalar objects. + mutable TObjArray fIndex; //! A sorted index of the scalars for faster searches. + mutable bool fIndexValid; //! Indicates that the index is valid. + + ClassDef(AliHLTMuonSpectroScalars, 1); // HLT trigger scalars for the muon spectrometer. +}; + +#endif // AliHLTMUONSPECTROSCALARS_H diff --git a/HLT/trigger/AliHLTMuonSpectroTriggerComponent.cxx b/HLT/trigger/AliHLTMuonSpectroTriggerComponent.cxx new file mode 100644 index 00000000000..78b4aef20f3 --- /dev/null +++ b/HLT/trigger/AliHLTMuonSpectroTriggerComponent.cxx @@ -0,0 +1,533 @@ +// $Id: $ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * All rights reserved. * + * * + * Primary Authors: * + * Artur Szostak * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/// @file AliHLTMuonSpectroTriggerComponent.cxx +/// @author Artur Szostak +/// @date 9 Nov 2009 +/// @brief Implementation of the muon spectrometer trigger component. +/// +/// The AliHLTMuonSpectroTriggerComponent component is used to generate the HLT +/// trigger for the muon spectrometer. + +#include "AliHLTMuonSpectroTriggerComponent.h" +#include "AliHLTTriggerDecision.h" +#include "AliHLTMuonSpectroScalars.h" +#include "AliHLTMUONDataBlockReader.h" +#include "AliHLTMUONConstants.h" +#include "AliHLTMUONUtils.h" +#include "AliMUONTriggerDDLDecoderEventHandler.h" + +ClassImp(AliHLTMuonSpectroTriggerComponent); + + +AliHLTMuonSpectroTriggerComponent::AliHLTMuonSpectroTriggerComponent() : + AliHLTTrigger(), + fBufferSizeConst(1024*16), + fBufferSizeMultiplier(1), + fMakeStats(false), + fTriggerHits(false), + fTriggerTrigRecs(false), + fTriggerTracks(true), + fTriggerDimuons(true) +{ + // Default constructor. +} + + +AliHLTMuonSpectroTriggerComponent::~AliHLTMuonSpectroTriggerComponent() +{ + // Default destructor. +} + + +void AliHLTMuonSpectroTriggerComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list) const +{ + // Returns the list of input types expected. + + list.push_back(AliHLTMUONConstants::TriggerRecordsBlockDataType()); + list.push_back(AliHLTMUONConstants::RecHitsBlockDataType()); + list.push_back(AliHLTMUONConstants::MansoTracksBlockDataType()); + list.push_back(AliHLTMUONConstants::SinglesDecisionBlockDataType()); + list.push_back(AliHLTMUONConstants::PairsDecisionBlockDataType()); +} + + +void AliHLTMuonSpectroTriggerComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list) const +{ + // Return the output data types generated. + + list.push_back(kAliHLTDataTypeTriggerDecision); + list.push_back(kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT); +} + + +void AliHLTMuonSpectroTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) +{ + // Returns the output data size estimate. + + constBase = fBufferSizeConst; + inputMultiplier = fBufferSizeMultiplier; +} + + +AliHLTComponent* AliHLTMuonSpectroTriggerComponent::Spawn() +{ + // Creates and returns a new instance. + + return new AliHLTMuonSpectroTriggerComponent; +} + + +Int_t AliHLTMuonSpectroTriggerComponent::DoInit(int argc, const char** argv) +{ + // Initialise the component. + + fMakeStats = false; + fTriggerHits = false; + fTriggerTrigRecs = false; + fTriggerTracks = false; + fTriggerDimuons = false; + + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "-makestats") == 0) + { + fMakeStats = true; + continue; + } + if (strcmp(argv[i], "-triggerhits") == 0) + { + fTriggerHits = true; + continue; + } + if (strcmp(argv[i], "-triggertrigrecs") == 0) + { + fTriggerTrigRecs = true; + continue; + } + if (strcmp(argv[i], "-triggertracks") == 0) + { + fTriggerTracks = true; + continue; + } + if (strcmp(argv[i], "-triggerdimuons") == 0) + { + fTriggerDimuons = true; + continue; + } + if (strcmp(argv[i], "-triggerany") == 0) + { + fTriggerHits = true; + fTriggerTrigRecs = true; + fTriggerTracks = true; + fTriggerDimuons = true; + continue; + } + + HLTError("Unknown option '%s'.", argv[i]); + return -EINVAL; + } // for loop + + // If nothing was turned on to trigger then turn everything on by default. + if (fTriggerHits == false and fTriggerTrigRecs == false + and fTriggerTracks == false and fTriggerDimuons == false + ) + { + fTriggerTracks = true; + fTriggerDimuons = true; + } + + return 0; +} + + +Int_t AliHLTMuonSpectroTriggerComponent::DoDeinit() +{ + // Cleans up the component. + + return 0; +} + + +int AliHLTMuonSpectroTriggerComponent::DoTrigger() +{ + // Applies the trigger for the HLT. + + int result = 0; + + bool gothits = false; + bool gottrigrecs = false; + bool gottracks = false; + bool gotsingles = false; + bool gotpairs = false; + UInt_t nhits = 0; + UInt_t nhitsMTR = 0; + UInt_t nhitsMCH = 0; + UInt_t nhitsCh[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + UInt_t ntrigrecs = 0; + UInt_t nL0plus = 0; + UInt_t nL0minus = 0; + UInt_t ntracksMT = 0; // from Manso track blocks. + UInt_t ntracksSD = 0; // from singles decision blocks + UInt_t nplus = 0; + UInt_t nminus = 0; + UInt_t nlowpt = 0; + UInt_t nhighpt = 0; + Double_t minpt = -1; + Double_t maxpt = -1; + UInt_t nlikeany = 0; + UInt_t nlikelow = 0; + UInt_t nlikehigh = 0; + UInt_t nunlikeany = 0; + UInt_t nunlikelow = 0; + UInt_t nunlikehigh = 0; + UInt_t nlowmass = 0; + UInt_t nhighmass = 0; + Double_t minmass = -1; + Double_t maxmass = -1; + + + AliHLTComponentDataType blockType = AliHLTMUONConstants::TriggerRecordsBlockDataType(); + for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType); + block != NULL; + block = GetNextInputBlock() + ) + { + AliHLTMUONTriggerRecordsBlockReader trigRecsBlock(block->fPtr, block->fSize); + if (not IsBlockOk(trigRecsBlock, blockType)) + { + HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str()); + continue; + } + gothits = true; + + ntrigrecs += trigRecsBlock.Nentries(); + for (AliHLTUInt32_t i = 0; i < trigRecsBlock.Nentries(); ++i) + { + AliHLTMUONParticleSign sign; + bool hitset[4]; + AliHLTMUONUtils::UnpackTriggerRecordFlags(trigRecsBlock[i].fFlags, sign, hitset); + switch (sign) + { + case kSignPlus: ++nL0plus; break; + case kSignMinus: ++nL0minus; break; + default: break; + } + for (int j = 0; j < 4; ++j) + { + if (hitset[j]) + { + ++nhitsCh[j+10]; + ++nhits; + ++nhitsMTR; + } + } + } + } + + blockType = AliHLTMUONConstants::RecHitsBlockDataType(); + for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType); + block != NULL; + block = GetNextInputBlock() + ) + { + AliHLTMUONRecHitsBlockReader hitsBlock(block->fPtr, block->fSize); + if (not IsBlockOk(hitsBlock, blockType)) + { + HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str()); + continue; + } + gottrigrecs = true; + + nhits += hitsBlock.Nentries(); + nhitsMCH += hitsBlock.Nentries(); + for (AliHLTUInt32_t i = 0; i < hitsBlock.Nentries(); ++i) + { + AliHLTUInt8_t chamber; + AliHLTUInt16_t detElemId; + AliHLTMUONUtils::UnpackRecHitFlags(hitsBlock[i].fFlags, chamber, detElemId); + if (chamber < 10) + { + ++nhitsCh[chamber]; + } + else + { + HLTWarning("Received a reconstructed hit which indicates" + " an invalid chamber number of %d. The expected" + " range is [0..9]. The data blockis probably corrupt.", + int(chamber) + ); + } + } + } + + blockType = AliHLTMUONConstants::MansoTracksBlockDataType(); + for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType); + block != NULL; + block = GetNextInputBlock() + ) + { + AliHLTMUONMansoTracksBlockReader tracksBlock(block->fPtr, block->fSize); + if (not IsBlockOk(tracksBlock, blockType)) + { + HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str()); + continue; + } + gottracks = true; + + ntracksMT += tracksBlock.Nentries(); + for (AliHLTUInt32_t i = 0; i < tracksBlock.Nentries(); ++i) + { + AliHLTMUONParticleSign sign; + bool hitset[4]; + AliHLTMUONUtils::UnpackMansoTrackFlags(tracksBlock[i].fFlags, sign, hitset); + switch (sign) + { + case kSignPlus: ++nplus; break; + case kSignMinus: ++nminus; break; + default: break; + } + } + } + + blockType = AliHLTMUONConstants::SinglesDecisionBlockDataType(); + for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType); + block != NULL; + block = GetNextInputBlock() + ) + { + AliHLTMUONSinglesDecisionBlockReader singlesBlock(block->fPtr, block->fSize); + if (not IsBlockOk(singlesBlock, blockType)) + { + HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str()); + continue; + } + gotsingles = true; + + ntracksSD += singlesBlock.Nentries(); + nlowpt += singlesBlock.BlockHeader().fNlowPt; + nhighpt += singlesBlock.BlockHeader().fNhighPt; + for (AliHLTUInt32_t i = 0; i < singlesBlock.Nentries(); ++i) + { + if (singlesBlock[i].fPt < minpt or minpt == -1) minpt = singlesBlock[i].fPt; + if (singlesBlock[i].fPt > maxpt or maxpt == -1) maxpt = singlesBlock[i].fPt; + } + } + + blockType = AliHLTMUONConstants::PairsDecisionBlockDataType(); + for (const AliHLTComponentBlockData* block = GetFirstInputBlock(blockType); + block != NULL; + block = GetNextInputBlock() + ) + { + AliHLTMUONPairsDecisionBlockReader pairsBlock(block->fPtr, block->fSize); + if (not IsBlockOk(pairsBlock, blockType)) + { + HLTWarning("Skipping problematic block '%s'", DataType2Text(blockType).c_str()); + continue; + } + gotpairs = true; + + nunlikeany += pairsBlock.BlockHeader().fNunlikeAnyPt; + nlikeany += pairsBlock.BlockHeader().fNlikeAnyPt; + // Dont use the other scalars from the pair decisions block header because + // they are much more restrictive. They count pairs where both tracks pass + // the low or high pT cut. But we want to relax this to just one track needs + // to pass the pT cut. + for (AliHLTUInt32_t i = 0; i < pairsBlock.Nentries(); ++i) + { + if (pairsBlock[i].fInvMass < minmass or minmass == -1) minmass = pairsBlock[i].fInvMass; + if (pairsBlock[i].fInvMass > maxmass or maxmass == -1) maxmass = pairsBlock[i].fInvMass; + bool highMass, lowMass, unlike; + AliHLTUInt8_t highPtCount, lowPtCount; + AliHLTMUONUtils::UnpackPairDecisionBits( + pairsBlock[i].fTriggerBits, highMass, lowMass, unlike, + highPtCount, lowPtCount + ); + if (unlike) + { + if (lowPtCount >= 1) ++nunlikelow; + if (highPtCount >= 1) ++nunlikehigh; + if (lowMass) ++nlowmass; + if (highMass) ++nhighmass; + } + else + { + if (lowPtCount >= 1) ++nlikelow; + if (highPtCount >= 1) ++nlikehigh; + } + } + } + + // Select the largest value for nTracks since we might only get this information + // from singles decision blocks. + UInt_t ntracks = ntracksSD > ntracksMT ? ntracksSD : ntracksMT; + + bool triggeredOnHits = fTriggerHits and nhitsMCH > 0; + bool triggeredOnTrigRecs = fTriggerTrigRecs and ntrigrecs > 0; + bool triggeredOnTracks = fTriggerTracks and ntracks > 0; + bool triggeredOnDimuons = fTriggerDimuons and (nunlikeany > 0 + or nunlikelow > 0 or nunlikehigh > 0 or nlowmass > 0 or nhighmass > 0); + + if (triggeredOnDimuons) + { + SetDescription("Dimuon in muon spectrometer"); + SetTriggerDomain(AliHLTTriggerDomain("*******:MUON")); + } + else if (triggeredOnTracks) + { + SetDescription("Tracks in muon spectrometer"); + SetTriggerDomain(AliHLTTriggerDomain("*******:MUON")); + } + else if (triggeredOnTrigRecs) + { + SetDescription("Muon trigger chambers triggered"); + if (triggeredOnHits) + { + SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRG | AliHLTReadoutList::kMUONTRK)); + SetTriggerDomain(AliHLTTriggerDomain("TRIGRECS:MUON,RECHITS :MUON")); + } + else + { + SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRG)); + SetTriggerDomain(AliHLTTriggerDomain("TRIGRECS:MUON")); + } + } + else if (triggeredOnHits) + { + SetDescription("Hits in muon tracking chambers"); + SetReadoutList(AliHLTReadoutList(AliHLTReadoutList::kMUONTRK)); + SetTriggerDomain(AliHLTTriggerDomain("RECHITS :MUON")); + } + else + { + SetDescription("Not triggered"); + SetTriggerDomain(AliHLTTriggerDomain()); + } + + if (triggeredOnDimuons or triggeredOnTracks or triggeredOnTrigRecs or triggeredOnHits) + { + result = TriggerEvent(); + if (result == -ENOSPC) goto increaseBuffer; + if (result != 0) return result; + } + + if (fMakeStats) + { + AliHLTMuonSpectroScalars scalars; + if (gothits and gottrigrecs) scalars.Add("NHits", "Total number of hits", nhits); + if (gottrigrecs) scalars.Add("NHitsMTR", "Number of hits in trigger chambers", nhitsMTR); + if (gothits) + { + scalars.Add("NHitsMCH", "Number of hits in tracking chambers", nhitsMCH); + for (int i = 0; i < 10; i++) + { + scalars.Add(Form("NHitsCh%d", i+1), Form("Number of hits in chamber %d", i+1), nhitsCh[i]); + } + } + if (gottrigrecs) + { + for (int i = 10; i < 14; i++) + { + scalars.Add(Form("NHitsCh%d", i+1), Form("Number of hits in chamber %d", i+1), nhitsCh[i]); + } + scalars.Add("NTrigRecs", "Total number of trigger records", ntrigrecs); + scalars.Add("NL0+", "Number of positive sign tracks in L0", nL0plus); + scalars.Add("NL0-", "Number of negative sign tracks in L0", nL0minus); + } + if (gottracks or gotsingles) scalars.Add("NTracks", "Total number of tracks", ntracks); + if (gottracks) + { + scalars.Add("N+", "Number of positive sign tracks", nplus); + scalars.Add("N-", "Number of negative sign tracks", nminus); + } + if (gotsingles) + { + scalars.Add("NLowPt", "Number of low pT tracks", nlowpt); + scalars.Add("NHighPt", "Number of high pT tracks", nhighpt); + scalars.Add("MinPt", "Minimum pT found (GeV/c)", minpt); + scalars.Add("MaxPt", "Maximum pT found (GeV/c)", maxpt); + } + if (gotpairs) + { + scalars.Add("NLikeAny", "Number of like sign track pairs", nlikeany); + scalars.Add("NLikeLow", "Number of like sign pairs with at least 1 low pT track.", nlikelow); + scalars.Add("NLikeHigh", "Number of like sign pairs with at least 1 high pT track.", nlikehigh); + scalars.Add("NUnlikeAny", "Number of unlike sign track pairs", nunlikeany); + scalars.Add("NUnlikeLow", "Number of unlike sign pairs with at least 1 low pT track.", nunlikelow); + scalars.Add("NUnlikeHigh", "Number of unlike sign pairs with at least 1 high pT track.", nunlikehigh); + scalars.Add("NLowMass", "Number of low mass dimuons", nlowmass); + scalars.Add("NHighMass", "Number of high mass dimuons", nhighmass); + scalars.Add("MinMass", "Minimum invariant mass found for dimuon (GeV/c^2)", minmass); + scalars.Add("MaxMass", "Maximum invariant mass found for dimuon (GeV/c^2)", maxmass); + } + + result = PushBack(&scalars, kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT); + if (result == -ENOSPC) goto increaseBuffer; + } + return result; + +increaseBuffer: + // Increase the estimated buffer space required since the PushBack + // or TriggerEvent methods indicate that they ran out of buffer space. + fBufferSizeConst += 1024*1024; + fBufferSizeMultiplier *= 2.; + return -ENOSPC; +} + + +template +bool AliHLTMuonSpectroTriggerComponent::IsBlockOk( + const BlockReader& reader, const AliHLTComponentDataType& type + ) const +{ + // Method for checking the block structure. + + if (not reader.BufferSizeOk()) + { + string name = DataType2Text(type).c_str(); + size_t headerSize = sizeof(typename BlockReader::HeaderType); + if (reader.BufferSize() < headerSize) + { + HLTError("Received a '%s' data block with a size of %d bytes," + " which is smaller than the minimum valid size of %d bytes." + " The block must be corrupt.", + name.c_str(), reader.BufferSize(), headerSize + ); + } + + size_t expectedWidth = sizeof(typename BlockReader::ElementType); + if (reader.CommonBlockHeader().fRecordWidth != expectedWidth) + { + HLTError("Received a '%s' data block with a record" + " width of %d bytes, but the expected value is %d bytes." + " The block might be corrupt.", + name.c_str(), + reader.CommonBlockHeader().fRecordWidth, + expectedWidth + ); + } + + HLTError("Received a '%s' data block with a size of %d bytes," + " but the block header claims the block should be %d bytes." + " The block might be corrupt.", + name.c_str(), reader.BufferSize(), reader.BytesUsed() + ); + return false; + } + return true; +} diff --git a/HLT/trigger/AliHLTMuonSpectroTriggerComponent.h b/HLT/trigger/AliHLTMuonSpectroTriggerComponent.h new file mode 100644 index 00000000000..e0131ba1d48 --- /dev/null +++ b/HLT/trigger/AliHLTMuonSpectroTriggerComponent.h @@ -0,0 +1,188 @@ +//-*- Mode: C++ -*- +// $Id: $ +#ifndef AliHLTMUONSPECTROTRIGGERCOMPONENT_H +#define AliHLTMUONSPECTROTRIGGERCOMPONENT_H +/* This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/// @file AliHLTMuonSpectroTriggerComponent.h +/// @author Artur Szostak +/// @date 9 Nov 2009 +/// @brief Declares the trigger component for the muon spectrometer. + +#include "AliHLTTrigger.h" + +/** + * \class AliHLTMuonSpectroTriggerComponent + * \brief Muon spectrometer trigger component. + * + * This component takes the HLT MUON decision generated by the AliHLTMUONDecisionComponent + * and creates a HLT trigger suitable for the HLT global trigger framework. Some + * optional summary statistics scalars can be generated with the "-makestats" option. + * This extra statistics information is filled in the AliHLTMuonSpectroScalars object, + * and written to a kAliHLTDataTypeEventStatistics type data block. Thus, the scalars + * object can be automatically added to the AliHLTEventSummary object by the + * AliHLTEventSummaryProducerComponent. + * + *

General properties:

+ * + * Component ID: \b MuonSpectroTrigger
+ * Library: \b libAliHLTTrigger.so
+ * Input Data Types: \li AliHLTMUONConstants::TriggerRecordsBlockDataType() = "TRIGRECS:MUON"
+ * \li AliHLTMUONConstants::RecHitsBlockDataType() = "RECHITS :MUON"
+ * \li AliHLTMUONConstants::MansoTracksBlockDataType() = "MANTRACK:MUON"
+ * \li AliHLTMUONConstants::SinglesDecisionBlockDataType() = "DECIDSIN:MUON"
+ * \li AliHLTMUONConstants::PairsDecisionBlockDataType() = "DECIDPAR:MUON"
+ * Output Data Types: \li kAliHLTDataTypeTriggerDecision = "TRIG_DEC:HLT "
+ * \li kAliHLTDataTypeReadoutList = "HLTRDLST:HLT "
+ * \li kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT = "EV_STATI:HLT "
+ * + *

Mandatory arguments:

+ * None. + * + *

Optional arguments:

+ * \li -makestats
+ * If specified then the summary statistics scalars object is generated as output. + * The default is not to generate the statistics object.
+ * \li -triggerhits
+ * Indicates that the component should trigger if any hits are found in the muon + * spectrometer tracking chambers. This option requires that this trigger component + * receives the reconstructed hits data blocks.
+ * \li -triggertrigrecs
+ * Indicates that the component should trigger if any trigger records are found. + * This option requires that this trigger component receives the trigger records + * data blocks.
+ * \li -triggertracks
+ * Indicates that the component should trigger if any Manso tracks are found. + * This option requires that this trigger component receives the Manso track + * or singles decision data blocks.
+ * \li -triggerdimuons
+ * Indicates that the component should trigger if any dimuon pairs are found. + * This option requires that this trigger component receives the pairs decision + * data blocks.
+ * \li -triggerany
+ * This option indicates that the trigger component should trigger if anything was + * reconstructed in the muon spectrometer by the dHLT at all.
+ * + * \note If none of the "triggerhits", "-triggertrigrecs", "-triggertracks" or "-triggerdimuons" + * options are specified then the default triggering mode is to trigger on tracks + * and dimuon pairs.
+ * + *

Configuration:

+ * Currently there is no configuration required. + * + *

Default CDB entries:

+ * None. + * + *

Performance:

+ * Under a millisecond per event. + * + *

Memory consumption:

+ * Memory consumption is minimal. It should be less than 1 MBytes. + * + *

Output size:

+ * Requires up to 4 kBytes + * + * \ingroup alihlt_trigger_components + */ +class AliHLTMuonSpectroTriggerComponent : public AliHLTTrigger +{ +public: + AliHLTMuonSpectroTriggerComponent(); + virtual ~AliHLTMuonSpectroTriggerComponent(); + + /** + * Inherited from AliHLTTrigger. + * @return string containing the global trigger name. + */ + virtual const char* GetTriggerName() const { return "MuonSpectroTrigger"; } + + /** + * Inherited from AliHLTTrigger. Returns the following input data types + * handled by this component: + * AliHLTMUONConstants::TriggerRecordsBlockDataType() = "TRIGRECS:MUON" + * AliHLTMUONConstants::RecHitsBlockDataType() = "RECHITS :MUON" + * AliHLTMUONConstants::MansoTracksBlockDataType() = "MANTRACK:MUON" + * AliHLTMUONConstants::SinglesDecisionBlockDataType() = "DECIDSIN:MUON" + * AliHLTMUONConstants::PairsDecisionBlockDataType() = "DECIDPAR:MUON" + * @param list [out]: The list of data types to be filled. + */ + virtual void GetInputDataTypes(AliHLTComponentDataTypeList& list) const; + + /** + * Inherited from AliHLTTrigger. Returns the following output types generated + * by this component: + * kAliHLTDataTypeTriggerDecision + * kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT + * Including the type kAliHLTDataTypeReadoutList implicitly. + * @param list [out]: The list of data types to be filled. + */ + virtual void GetOutputDataTypes(AliHLTComponentDataTypeList& list) const; + + /** + * Inherited from AliHLTTrigger. Returns the estimated data volume required + * in bytes: constBase + input_volume * inputMultiplier + * @param constBase [out]: additive part, independent of the + * input data volume. + * @param inputMultiplier [out]: multiplication ratio + */ + virtual void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier); + + /** + * Inherited from AliHLTComponent. + * \returns a new instance of AliHLTMuonSpectroTriggerComponent. + */ + virtual AliHLTComponent* Spawn(); + +protected: + + /** + * Inherited from AliHLTComponent. Initialises the component. + * \param argc The number of arguments in argv. + * \param argv Array of component argument strings. + * \returns Zero on success and negative number on failure. + */ + virtual Int_t DoInit(int argc, const char** argv); + + /** + * Inherited from AliHLTComponent. Cleans up the component. + * \returns Zero on success and negative number on failure. + */ + virtual Int_t DoDeinit(); + + /** + * Inherited from AliHLTComponent. Makes a trigger decision for the muon + * spectrometer. + * @return Zero is returned on success and a negative error code on failure. + */ + virtual int DoTrigger(); + +private: + + /// Not implemented. Do not allow copying of this class. + AliHLTMuonSpectroTriggerComponent(const AliHLTMuonSpectroTriggerComponent& /*obj*/); + /// Not implemented. Do not allow copying of this class. + AliHLTMuonSpectroTriggerComponent& operator = (const AliHLTMuonSpectroTriggerComponent& /*obj*/); + + /** + * Method for checking the structure of a data block. + * \param reader The reader for the data block. + * \param type The data block type as given by the pub/sub framework. + * \returns true if the data block structure is OK and false otherwise. + */ + template + bool IsBlockOk(const BlockReader& reader, const AliHLTComponentDataType& type) const; + + unsigned long fBufferSizeConst; //! Constant size estimate for GetOutputDataSize. + double fBufferSizeMultiplier; //! Buffer size multiplier estimate for GetOutputDataSize. + bool fMakeStats; //! Indicates if the statistics scalars object should be generated or not. + bool fTriggerHits; //! If true then the component will trigger on any hits in the tracking chambers. + bool fTriggerTrigRecs; //! If true then the component will trigger on any trigger records. + bool fTriggerTracks; //! If true then the component will trigger on any tracks found. + bool fTriggerDimuons; //! If true then the component will trigger on any dimuons. + + ClassDef(AliHLTMuonSpectroTriggerComponent, 0); // Trigger component for the muon spectrometer. +}; + +#endif // AliHLTMUONSPECTROTRIGGERCOMPONENT_H diff --git a/HLT/trigger/AliHLTTriggerAgent.cxx b/HLT/trigger/AliHLTTriggerAgent.cxx index b2abff1a031..f26efc1e593 100644 --- a/HLT/trigger/AliHLTTriggerAgent.cxx +++ b/HLT/trigger/AliHLTTriggerAgent.cxx @@ -45,6 +45,7 @@ #include "AliHLTTriggerPhosMip.h" #include "AliHLTTriggerTrdClusterMultiplicity.h" #include "AliHLTTriggerGammaConversion.h" +#include "AliHLTMuonSpectroTriggerComponent.h" /** global instance for agent registration */ AliHLTTriggerAgent gAliHLTTriggerAgent; @@ -83,6 +84,7 @@ int AliHLTTriggerAgent::RegisterComponents(AliHLTComponentHandler* pHandler) con pHandler->AddComponent(new AliHLTTriggerPhosMip); pHandler->AddComponent(new AliHLTTriggerTrdClusterMultiplicity); pHandler->AddComponent(new AliHLTTriggerGammaConversion); + pHandler->AddComponent(new AliHLTMuonSpectroTriggerComponent); return 0; } @@ -126,6 +128,30 @@ int AliHLTTriggerAgent::CreateConfigurations(AliHLTConfigurationHandler* pHandle } else { HLTWarning("No inputs for %s found, skipping component", configurationId.Data()); } + + ///////////////////////////////////////////////////////////////////////////////////// + // The muon spectrometer trigger + configurationId = "TRIGGER-Muon-Spectrometer"; + + // define the inputsfor the muon spectrometer trigger. + if (pHandler->FindConfiguration("dHLT-sim-fromRaw")) { + triggerInputs = "dHLT-sim-fromRaw"; + } + else if (pHandler->FindConfiguration("dHLT-sim")) { + triggerInputs = "dHLT-sim"; + } + else if (pHandler->FindConfiguration("dHLT-sim-fromMC")) { + triggerInputs = "dHLT-sim-fromMC"; + } + + if (triggerInputs.Length() > 0) { + HLTInfo("Configuring inputs for %s: %s", configurationId.Data(), triggerInputs.Data()); + pHandler->CreateConfiguration(configurationId.Data(), "MuonSpectroTrigger", triggerInputs.Data(), "-makestats"); + if (triggerOutputs.Length() > 0) triggerOutputs += " "; + triggerOutputs += configurationId; + } else { + HLTWarning("No inputs for %s found, skipping component.", configurationId.Data()); + } ///////////////////////////////////////////////////////////////////////////////////// // @@ -156,7 +182,7 @@ const char* AliHLTTriggerAgent::GetRequiredComponentLibraries() const { // see header file for class documentation - return "libAliHLTUtil.so libAliHLTRCU.so libAliHLTTPC.so libAliHLTITS.so libAliHLTGlobal.so"; + return "libAliHLTUtil.so libAliHLTRCU.so libAliHLTTPC.so libAliHLTITS.so libAliHLTGlobal.so libAliHLTMUON.so"; } int AliHLTTriggerAgent::GetHandlerDescription(AliHLTComponentDataType dt, diff --git a/HLT/trigger/AliHLTTriggerLinkDef.h b/HLT/trigger/AliHLTTriggerLinkDef.h index bf8cd07f303..5ff8de492bc 100644 --- a/HLT/trigger/AliHLTTriggerLinkDef.h +++ b/HLT/trigger/AliHLTTriggerLinkDef.h @@ -28,4 +28,7 @@ #pragma link C++ class AliHLTTriggerDetectorGeomRectangle+; #pragma link C++ class AliHLTTriggerDecisionParameters+; #pragma link C++ class AliHLTTriggerGammaConversion+; +#pragma link C++ class AliHLTMuonSpectroScalars+; +#pragma link C++ class AliHLTMuonSpectroScalars::AliScalar+; +#pragma link C++ class AliHLTMuonSpectroTriggerComponent+; #endif diff --git a/HLT/trigger/CreateTriggerMenuCDBEntry.C b/HLT/trigger/CreateTriggerMenuCDBEntry.C index 8c979061e0b..278aefb5450 100644 --- a/HLT/trigger/CreateTriggerMenuCDBEntry.C +++ b/HLT/trigger/CreateTriggerMenuCDBEntry.C @@ -58,6 +58,9 @@ void CreateTriggerMenuCDBEntry( Int_t lastRun = AliCDBRunRange::Infinity() ) { + gSystem->Load("libAliHLTUtil.so"); + gSystem->Load("libAliHLTTRD.so"); + gSystem->Load("libAliHLTMUON.so"); gSystem->Load("libAliHLTTrigger.so"); // Setup the CDB default storage and run number. @@ -94,6 +97,7 @@ void CreateTriggerMenuCDBEntry( // NOTE: always make sure that the global HLT output and the HLT DDLs are included // in the readout, i.e. add domainHLTOUT|domainHLTDDL to the trigger domain config.AddItem("BarrelMultiplicityTrigger", "BarrelMultiplicityTrigger|domainHLTOUT|domainALLDDL", "charged barrel track multiplicity triggered"); + config.AddItem("MuonSpectroTrigger", "MuonSpectroTrigger|domainHLTOUT|domainALLDDL", "Muon spectrometer triggered"); /////////////////////////////////////////////////////////////////////////////////////////// // default domain in case there is no global trigger diff --git a/HLT/trigger/test/Makefile.am b/HLT/trigger/test/Makefile.am index 8b9bec1508a..4479e204e66 100644 --- a/HLT/trigger/test/Makefile.am +++ b/HLT/trigger/test/Makefile.am @@ -1,20 +1,24 @@ AM_CPPFLAGS = -I$(top_srcdir)/BASE \ -I$(srcdir)/.. \ + -I$(top_srcdir)/MUON \ + -I$(ALICE_ROOT)/MUON \ @ALIROOT_CPPFLAGS@ \ -I@ROOTINCDIR@ EXTRA_DIST = -check_PROGRAMS = testTriggerDomain testGlobalTriggerComponent +check_PROGRAMS = testTriggerDomain testGlobalTriggerComponent testMuonSpectroTrigger testTriggerDomain_SOURCES = testTriggerDomain.C testGlobalTriggerComponent_SOURCES = testGlobalTriggerComponent.C +testMuonSpectroTrigger_SOURCES = testMuonSpectroTrigger.C # linker flags LDADD_COMMON = $(top_builddir)/BASE/libHLTbase.la \ + $(top_builddir)/MUON/libAliHLTMUON.la \ $(top_builddir)/trigger/libAliHLTTrigger.la LDFLAGS_COMMON = -L@ROOTLIBDIR@ \ @ROOTLIBS@ \ @@ -29,5 +33,9 @@ testGlobalTriggerComponent_LDADD = $(LDADD_COMMON) testGlobalTriggerComponent_LDFLAGS = $(LDFLAGS_COMMON) +testMuonSpectroTrigger_LDADD = $(LDADD_COMMON) + +testMuonSpectroTrigger_LDFLAGS = $(LDFLAGS_COMMON) + TESTS = $(check_PROGRAMS) diff --git a/HLT/trigger/test/testMuonSpectroTrigger.C b/HLT/trigger/test/testMuonSpectroTrigger.C new file mode 100644 index 00000000000..808f5af7b23 --- /dev/null +++ b/HLT/trigger/test/testMuonSpectroTrigger.C @@ -0,0 +1,420 @@ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * * + * Primary Authors: Artur Szostak * + * for The ALICE HLT Project. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/** + * @file testMuonSpectroTrigger.C + * @author Artur Szostak + * @date 11 Nov 2008 + * + * This macro is used to test the AliHLTMuonSpectroTriggerComponent class. + * A basic test is run with the AliHLTSystem framework to check that the dHLT + * decision is interpreted correctly and the summary statistics generated properly. + */ + +#if defined(__CINT__) && (! defined(__MAKECINT__)) +#error This macro must be compiled. Try running as testMuonSpectroTrigger.C++, but remember to load the libAliHLTTrigger.so and libAliHLTMUON.so libraries first. +#endif + +#if !defined(__CINT__) || defined(__MAKECINT__) +#include "TSystem.h" +#include "TClassTable.h" +#include "TFile.h" +#include "AliLog.h" +#include "AliHLTReadoutList.h" +#include "AliHLTTriggerDomain.h" +#include "AliHLTTriggerDecision.h" +#include "AliHLTMuonSpectroScalars.h" +#include "AliHLTMUONDataBlockWriter.h" +#include "AliHLTMUONUtils.h" +#include "AliHLTSystem.h" +#include "AliHLTConfiguration.h" +#include "Riostream.h" +#include +#endif + +/** + * Writes the indicated buffer to the given file name. + * \returns true if the file was written correctly and false otherwise. + */ +bool WriteFile(const char* filename, void* buffer, unsigned int size) +{ + FILE* file = fopen(filename, "w"); + if (file == NULL) + { + cerr << "ERROR: Could not create file: " << filename << endl; + return false; + } + fwrite(buffer, size, 1, file); + fclose(file); + return true; +} + +/** + * Generates some sample input data and writes it into 6 files named + * testSinglesDecisionInputFile1.dat ... testSinglesDecisionInputFile3.dat and + * testPairsDecisionInputFile1.dat ... testPairsDecisionInputFile3.dat + */ +void GenerateInputData() +{ + if (gClassTable->GetID("AliHLTMuonSpectroTriggerComponent") < 0) + { + gSystem->Load("libAliHLTUtil.so"); + gSystem->Load("libAliHLTTRD.so"); + gSystem->Load("libAliHLTTrigger.so"); + } + + // Allocate two 1 MByte buffers, this will be more than enough space. + unsigned int bufferSize = 1024*1024; + void* buffer1 = new char[bufferSize]; + void* buffer2 = new char[bufferSize]; + + AliHLTMUONSinglesDecisionBlockWriter singlesBlock(buffer1, bufferSize); + singlesBlock.InitCommonHeader(); + AliHLTMUONSinglesDecisionBlockStruct& singlesHeader = singlesBlock.BlockHeader(); + singlesHeader.fNlowPt = 2; + singlesHeader.fNhighPt = 1; + singlesBlock.SetNumberOfEntries(3); + AliHLTMUONTrackDecisionStruct& track1 = singlesBlock[0]; + track1.fTrackId = 1; + track1.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(false, false); + track1.fPt = 0.9; + AliHLTMUONTrackDecisionStruct& track2 = singlesBlock[1]; + track2.fTrackId = 2; + track2.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(false, true); + track2.fPt = 1.8; + AliHLTMUONTrackDecisionStruct& track3 = singlesBlock[2]; + track3.fTrackId = 3; + track3.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(true, true); + track3.fPt = 3.1; + + AliHLTMUONPairsDecisionBlockWriter pairsBlock(buffer2, bufferSize); + pairsBlock.InitCommonHeader(); + AliHLTMUONPairsDecisionBlockStruct& pairsHeader = pairsBlock.BlockHeader(); + pairsHeader.fNunlikeAnyPt = 1; + pairsHeader.fNunlikeLowPt = 1; + pairsHeader.fNunlikeHighPt = 1; + pairsHeader.fNlikeAnyPt = 2; + pairsHeader.fNlikeLowPt = 2; + pairsHeader.fNlikeHighPt = 1; + pairsHeader.fNmassAny = 1; + pairsHeader.fNmassLow = 1; + pairsHeader.fNmassHigh = 0; + pairsBlock.SetNumberOfEntries(3); + AliHLTMUONPairDecisionStruct& pair1 = pairsBlock[0]; + pair1.fTrackAId = 1; + pair1.fTrackBId = 2; + pair1.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(false, false, false, 0, 1); + pair1.fInvMass = 0.1; + AliHLTMUONPairDecisionStruct& pair2 = pairsBlock[1]; + pair2.fTrackAId = 1; + pair2.fTrackBId = 3; + pair2.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(false, true, true, 1, 1); + pair2.fInvMass = 3.1; + AliHLTMUONPairDecisionStruct& pair3 = pairsBlock[2]; + pair3.fTrackAId = 2; + pair3.fTrackBId = 3; + pair3.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(true, true, false, 1, 2); + pair3.fInvMass = 10.1; + + if (! WriteFile("testSinglesDecisionInputFile1.dat", buffer1, singlesBlock.BytesUsed())) return; + if (! WriteFile("testPairsDecisionInputFile1.dat", buffer2, pairsBlock.BytesUsed())) return; + + singlesHeader.fNlowPt = 2; + singlesHeader.fNhighPt = 1; + singlesBlock.SetNumberOfEntries(2); + track1.fTrackId = 4; + track1.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(false, true); + track1.fPt = 1.2; + track2.fTrackId = 5; + track2.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(true, true); + track2.fPt = 2.3; + + pairsHeader.fNunlikeAnyPt = 1; + pairsHeader.fNunlikeLowPt = 1; + pairsHeader.fNunlikeHighPt = 1; + pairsHeader.fNlikeAnyPt = 0; + pairsHeader.fNlikeLowPt = 0; + pairsHeader.fNlikeHighPt = 0; + pairsHeader.fNmassAny = 1; + pairsHeader.fNmassLow = 1; + pairsHeader.fNmassHigh = 1; + pairsBlock.SetNumberOfEntries(1); + pair1.fTrackAId = 4; + pair1.fTrackBId = 5; + pair1.fTriggerBits = AliHLTMUONUtils::PackPairDecisionBits(true, true, true, 1, 2); + pair1.fInvMass = 9.7; + + if (! WriteFile("testSinglesDecisionInputFile2.dat", buffer1, singlesBlock.BytesUsed())) return; + if (! WriteFile("testPairsDecisionInputFile2.dat", buffer2, pairsBlock.BytesUsed())) return; + + singlesHeader.fNlowPt = 0; + singlesHeader.fNhighPt = 0; + singlesBlock.SetNumberOfEntries(1); + track1.fTrackId = 6; + track1.fTriggerBits = AliHLTMUONUtils::PackTrackDecisionBits(false, false); + track1.fPt = 0.6; + + pairsHeader.fNunlikeAnyPt = 0; + pairsHeader.fNunlikeLowPt = 0; + pairsHeader.fNunlikeHighPt = 0; + pairsHeader.fNlikeAnyPt = 0; + pairsHeader.fNlikeLowPt = 0; + pairsHeader.fNlikeHighPt = 0; + pairsHeader.fNmassAny = 0; + pairsHeader.fNmassLow = 0; + pairsHeader.fNmassHigh = 0; + pairsBlock.SetNumberOfEntries(0); + + if (! WriteFile("testSinglesDecisionInputFile3.dat", buffer1, singlesBlock.BytesUsed())) return; + if (! WriteFile("testPairsDecisionInputFile3.dat", buffer2, pairsBlock.BytesUsed())) return; +} + +/** + * Runs a small test chain for the muon spectrometer trigger component. + * \param debug If true then full logging is turned on. + * \param numOfEvents The number of events to run the chain for. + */ +void RunTrigger(bool debug = false, int numOfEvents = 3) +{ + AliHLTSystem sys; + sys.LoadComponentLibraries("libAliHLTUtil.so"); + sys.LoadComponentLibraries("libAliHLTTRD.so"); + sys.LoadComponentLibraries("libAliHLTMUON.so"); + sys.LoadComponentLibraries("libAliHLTTrigger.so"); + if (debug) + { + AliLog::SetGlobalLogLevel(AliLog::kMaxType); + sys.SetGlobalLoggingLevel(kHLTLogAll); + } + + TString cmdline = "-datatype DECIDSIN MUON "; + for (int i = 1; i <= 3; i++) + { + if (i > 1) cmdline += " -nextevent"; + cmdline += Form(" -datafile testSinglesDecisionInputFile%d.dat", i); + } + AliHLTConfiguration pub1("pub1", "FilePublisher", NULL, cmdline.Data()); + + cmdline = "-datatype DECIDPAR MUON "; + for (int i = 1; i <= 3; i++) + { + if (i > 1) cmdline += " -nextevent"; + cmdline += Form(" -datafile testPairsDecisionInputFile%d.dat", i); + } + AliHLTConfiguration pub2("pub2", "FilePublisher", NULL, cmdline.Data()); + + AliHLTConfiguration proc("proc", "MuonSpectroTrigger", "pub1 pub2", "-makestats -triggerdimuons"); + AliHLTConfiguration sink("sink", "ROOTFileWriter", "proc", "-datafile testMuonTriggerOutputFile.root -concatenate-events"); + + sys.BuildTaskList("sink"); + sys.Run(numOfEvents); +} + + +/** + * Checks that a particular decision and summary object are as expected and prints + * error messages if there are any problems with the results. + * \param eventNum The number of the event being checked. + * \param decision The trigger decision being checked. + * \param scalars The scalars object being checked. + * \param expectedResult The expected global trigger result. + * \param expectedDomain The expected resulting trigger domain. + * \param expectedDescription The expected resulting trigger description. + * \param expectedScalars The expected resulting scalars. + * \returns true if the decision and scalars are as expected. + */ +bool Check( + int eventNum, + AliHLTTriggerDecision* decision, + AliHLTMuonSpectroScalars* scalars, + bool expectedResult, + AliHLTTriggerDomain expectedDomain, + TString expectedDescription, + AliHLTMuonSpectroScalars& expectedScalars + ) +{ + if (decision == NULL) + { + cerr << "ERROR: No decision found where expected for event " + << eventNum << "." << endl; + return false; + } + if (decision->Result() != expectedResult) + { + cerr << "ERROR: The result does not match the expected value for event " + << eventNum << ". Got " << decision->Result() << " but expected " + << expectedResult << "." << endl; + return false; + } + if (decision->TriggerDomain() != expectedDomain) + { + cerr << "ERROR: The domain does not match the expected value for event " + << eventNum << ". Got:" << endl; + decision->TriggerDomain().Print(); + cerr << "but expected:" << endl; + expectedDomain.Print(); + return false; + } + if (decision->Description() != expectedDescription) + { + cerr << "ERROR: The description does not match the expected value for event " + << eventNum << ". Got '" << decision->Description() << "' but expected '" + << expectedDescription << "'." << endl; + return false; + } + if (*scalars != expectedScalars) + { + cerr << "ERROR: The scalars summary object does not match the expected one for event " + << eventNum << ". Expected the following scalar values:" << endl; + expectedScalars.Print(); + return false; + } + return true; +} + + +/// Routine for checking the results of the chain run in RunTrigger. +bool CheckResults() +{ + AliHLTTriggerDecision* decision = NULL; + AliHLTMuonSpectroScalars* scalars = NULL; + bool result = false; + + AliHLTTriggerDomain domainMUON("*******:MUON"); + //domainMUON.Add(AliHLTReadoutList("MUONTRK")); + + AliHLTMuonSpectroScalars emptyScalars; + + AliHLTMuonSpectroScalars scalarsEvent1; + scalarsEvent1.Add("NTracks", "", 3); + scalarsEvent1.Add("NLowPt", "", 2); + scalarsEvent1.Add("NHighPt", "", 1); + scalarsEvent1.Add("MinPt", "", 0.9f); + scalarsEvent1.Add("MaxPt", "", 3.1f); + scalarsEvent1.Add("NLikeAny", "", 2); + scalarsEvent1.Add("NLikeLow", "", 2); + scalarsEvent1.Add("NLikeHigh", "", 1); + scalarsEvent1.Add("NUnlikeAny", "", 1); + scalarsEvent1.Add("NUnlikeLow", "", 1); + scalarsEvent1.Add("NUnlikeHigh", "", 1); + scalarsEvent1.Add("NLowMass", "", 1); + scalarsEvent1.Add("NHighMass", "", 0); + scalarsEvent1.Add("MinMass", "", 0.1f); + scalarsEvent1.Add("MaxMass", "", 10.1f); + + AliHLTMuonSpectroScalars scalarsEvent2; + scalarsEvent2.Add("NTracks", "", 2); + scalarsEvent2.Add("NLowPt", "", 2); + scalarsEvent2.Add("NHighPt", "", 1); + scalarsEvent2.Add("MinPt", "", 1.2f); + scalarsEvent2.Add("MaxPt", "", 2.3f); + scalarsEvent2.Add("NLikeAny", "", 0); + scalarsEvent2.Add("NLikeLow", "", 0); + scalarsEvent2.Add("NLikeHigh", "", 0); + scalarsEvent2.Add("NUnlikeAny", "", 1); + scalarsEvent2.Add("NUnlikeLow", "", 1); + scalarsEvent2.Add("NUnlikeHigh", "", 1); + scalarsEvent2.Add("NLowMass", "", 1); + scalarsEvent2.Add("NHighMass", "", 1); + scalarsEvent2.Add("MinMass", "", 9.7f); + scalarsEvent2.Add("MaxMass", "", 9.7f); + + AliHLTMuonSpectroScalars scalarsEvent3; + scalarsEvent3.Add("NTracks", "", 1); + scalarsEvent3.Add("NLowPt", "", 0); + scalarsEvent3.Add("NHighPt", "", 0); + scalarsEvent3.Add("MinPt", "", 0.6f); + scalarsEvent3.Add("MaxPt", "", 0.6f); + scalarsEvent3.Add("NLikeAny", "", 0); + scalarsEvent3.Add("NLikeLow", "", 0); + scalarsEvent3.Add("NLikeHigh", "", 0); + scalarsEvent3.Add("NUnlikeAny", "", 0); + scalarsEvent3.Add("NUnlikeLow", "", 0); + scalarsEvent3.Add("NUnlikeHigh", "", 0); + scalarsEvent3.Add("NLowMass", "", 0); + scalarsEvent3.Add("NHighMass", "", 0); + scalarsEvent3.Add("MinMass", "", -1); + scalarsEvent3.Add("MaxMass", "", -1); + + TFile* file = new TFile("testMuonTriggerOutputFile.root", "READ"); + + // First event is the Start-Of-Run + decision = dynamic_cast(file->Get("MuonSpectroTrigger;1")); + scalars = dynamic_cast(file->Get("AliHLTMuonSpectroScalars;1")); + result = Check(0, decision, scalars, false, AliHLTTriggerDomain(), "Not triggered", emptyScalars); + if (! result) goto cleanup; + // Now we have the 3 data events: + decision = dynamic_cast(file->Get("MuonSpectroTrigger;2")); + scalars = dynamic_cast(file->Get("AliHLTMuonSpectroScalars;2")); + result = Check(1, decision, scalars, true, domainMUON, "Dimuon in muon spectrometer", scalarsEvent1); + if (! result) goto cleanup; + decision = dynamic_cast(file->Get("MuonSpectroTrigger;3")); + scalars = dynamic_cast(file->Get("AliHLTMuonSpectroScalars;3")); + result = Check(2, decision, scalars, true, domainMUON, "Dimuon in muon spectrometer", scalarsEvent2); + if (! result) goto cleanup; + decision = dynamic_cast(file->Get("MuonSpectroTrigger;4")); + scalars = dynamic_cast(file->Get("AliHLTMuonSpectroScalars;4")); + result = Check(3, decision, scalars, false, AliHLTTriggerDomain(), "Not triggered", scalarsEvent3); + if (! result) goto cleanup; + // and finally the End-Of-Run event. + decision = dynamic_cast(file->Get("MuonSpectroTrigger;5")); + scalars = dynamic_cast(file->Get("AliHLTMuonSpectroScalars;5")); + result = Check(4, decision, scalars, false, AliHLTTriggerDomain(), "Not triggered", emptyScalars); + if (! result) goto cleanup; + + delete file; + return true; + +cleanup: + if (decision != NULL) + { + cout << "========== Dumping received decision result ========== " << endl; + decision->Print(); + cout << "=========== Dumping received scalars result ========== " << endl; + scalars->Print(); + } + delete file; + return false; +} + + +/** + * Runs the unit test for the AliHLTMuonSpectroTriggerComponent class. + * \param debug If specified then the HLT chain is run with full logging enabled. + * \returns true if the class passed the test and false otherwise. + */ +bool testMuonSpectroTrigger(bool debug = false) +{ + GenerateInputData(); + RunTrigger(debug); + if (! CheckResults()) return false; + + // Cleanup all temporary files generated. + gSystem->Exec("rm -f testMuonTriggerOutputFile.root test*DecisionInputFile*.root"); + return true; +} + + +#ifndef __MAKECINT__ + +int main(int /*argc*/, const char** /*argv*/) +{ + bool resultOk = testMuonSpectroTrigger(); + if (not resultOk) return 1; + return 0; +} + +#endif // __MAKECINT__ diff --git a/OCDB/HLT/ConfigHLT/HLTGlobalTrigger/Run0_999999999_v0_s2.root b/OCDB/HLT/ConfigHLT/HLTGlobalTrigger/Run0_999999999_v0_s2.root new file mode 100644 index 0000000000000000000000000000000000000000..ebb28e4b42e568c95913d155438eb9f69791e2ea GIT binary patch literal 4599 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