]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
Adding HLT trigger component for the muon spectrometer to fit within the HLT trigger...
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 13 Nov 2009 12:11:01 +0000 (12:11 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 13 Nov 2009 12:11:01 +0000 (12:11 +0000)
12 files changed:
HLT/CMake_libAliHLTTrigger.txt
HLT/libAliHLTTrigger.pkg
HLT/trigger/AliHLTMuonSpectroScalars.cxx [new file with mode: 0644]
HLT/trigger/AliHLTMuonSpectroScalars.h [new file with mode: 0644]
HLT/trigger/AliHLTMuonSpectroTriggerComponent.cxx [new file with mode: 0644]
HLT/trigger/AliHLTMuonSpectroTriggerComponent.h [new file with mode: 0644]
HLT/trigger/AliHLTTriggerAgent.cxx
HLT/trigger/AliHLTTriggerLinkDef.h
HLT/trigger/CreateTriggerMenuCDBEntry.C
HLT/trigger/test/Makefile.am
HLT/trigger/test/testMuonSpectroTrigger.C [new file with mode: 0644]
OCDB/HLT/ConfigHLT/HLTGlobalTrigger/Run0_999999999_v0_s2.root [new file with mode: 0644]

index f65d3208e26c4eefde2b020d4e5f0897fb5b6f52..e4cf0dc0a0fa96c5ea6e7db3239e9e5fa6c76894 100644 (file)
@@ -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
index 5e26cc32c5c0478f049982b722e6306ff93af3f3..c01f789547f6b6fe3af7bb0935eacf219f27ee1f 100644 (file)
@@ -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 (file)
index 0000000..208625f
--- /dev/null
@@ -0,0 +1,387 @@
+// $Id: $
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * All rights reserved.                                                   *
+ *                                                                        *
+ * Primary Authors:                                                       *
+ *   Artur Szostak <artursz@iafrica.com>                                  *
+ *                                                                        *
+ * 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 <artursz@iafrica.com>
+///  @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<AliScalar*>( 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<const AliScalar*>( 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<AliScalar*>( 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<const AliScalar*>( 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<AliScalar*>( 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<AliHLTMuonSpectroScalars*>(&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<AliScalar*>( 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<AliScalar*>( 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<AliScalar*>( 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<AliScalar*>( obj.fScalars.UncheckedAt(i) );
+               Int_t n = fIndex.BinarySearch(scalar1);
+               if (n == -1) return false;
+               AliScalar* scalar2 = static_cast<AliScalar*>( 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<AliHLTMuonSpectroScalars::AliScalar*>(&object);
+       *obj = *this;
+}
diff --git a/HLT/trigger/AliHLTMuonSpectroScalars.h b/HLT/trigger/AliHLTMuonSpectroScalars.h
new file mode 100644 (file)
index 0000000..2d7de1a
--- /dev/null
@@ -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 <artursz@iafrica.com>
+///  @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 <i>n</i> 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 <i>n</i> 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 <i>n</i> 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 <i>n</i> 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 <i>n</i> 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 <i>n</i> 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 (file)
index 0000000..78b4aef
--- /dev/null
@@ -0,0 +1,533 @@
+// $Id: $
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * All rights reserved.                                                   *
+ *                                                                        *
+ * Primary Authors:                                                       *
+ *   Artur Szostak <artursz@iafrica.com>                                  *
+ *                                                                        *
+ * 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 <artursz@iafrica.com>
+/// @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 <typename BlockReader>
+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 (file)
index 0000000..e0131ba
--- /dev/null
@@ -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 <artursz@iafrica.com>
+/// @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.
+ *
+ * <h2>General properties:</h2>
+ *
+ * Component ID: \b MuonSpectroTrigger <br>
+ * Library: \b libAliHLTTrigger.so <br>
+ * Input Data Types: \li AliHLTMUONConstants::TriggerRecordsBlockDataType()  = "TRIGRECS:MUON" <br>
+ *                   \li AliHLTMUONConstants::RecHitsBlockDataType()         = "RECHITS :MUON" <br>
+ *                   \li AliHLTMUONConstants::MansoTracksBlockDataType()     = "MANTRACK:MUON" <br>
+ *                   \li AliHLTMUONConstants::SinglesDecisionBlockDataType() = "DECIDSIN:MUON" <br>
+ *                   \li AliHLTMUONConstants::PairsDecisionBlockDataType()   = "DECIDPAR:MUON" <br>
+ * Output Data Types: \li kAliHLTDataTypeTriggerDecision                      = "TRIG_DEC:HLT " <br>
+ *                    \li kAliHLTDataTypeReadoutList                          = "HLTRDLST:HLT " <br>
+ *                    \li kAliHLTDataTypeEventStatistics|kAliHLTDataOriginHLT = "EV_STATI:HLT " <br>
+ *
+ * <h2>Mandatory arguments:</h2>
+ * None.
+ *
+ * <h2>Optional arguments:</h2>
+ * \li -makestats <br>
+ *      If specified then the summary statistics scalars object is generated as output.
+ *      The default is not to generate the statistics object. <br>
+ * \li -triggerhits <br>
+ *      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. <br>
+ * \li -triggertrigrecs <br>
+ *      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. <br>
+ * \li -triggertracks <br>
+ *      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. <br>
+ * \li -triggerdimuons <br>
+ *      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. <br>
+ * \li -triggerany <br>
+ *      This option indicates that the trigger component should trigger if anything was
+ *      reconstructed in the muon spectrometer by the dHLT at all. <br>
+ *
+ * \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. <br>
+ *
+ * <h2>Configuration:</h2>
+ * Currently there is no configuration required.
+ *
+ * <h2>Default CDB entries:</h2>
+ * None.
+ *
+ * <h2>Performance:</h2>
+ * Under a millisecond per event.
+ *
+ * <h2>Memory consumption:</h2>
+ * Memory consumption is minimal. It should be less than 1 MBytes.
+ *
+ * <h2>Output size:</h2>
+ * 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 <i>[out]</i>: 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 <i>[out]</i>: 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        <i>[out]</i>: additive part, independent of the
+        *                                   input data volume.
+        * @param inputMultiplier  <i>[out]</i>: 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 <typename BlockReader>
+       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
index b2abff1a031e7783eac86557fec56325eeffcbe8..f26efc1e59322186d4a65bd21a9460e9475b95a2 100644 (file)
@@ -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,
index bf8cd07f303931bcda3b66b8ad4adc46c398c9d8..5ff8de492bc826786795067fa9259ff8fcb272b6 100644 (file)
@@ -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
index 8c979061e0b291cac31a2c150f466ec9e3a278e5..278aefb5450405ef1a78d8b1bb4d0bae94fb8957 100644 (file)
@@ -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
index 8b9bec1508ab688070d6ac124374c3fd86ee582d..4479e204e6632e54d9fa1cdac33efb90307a8eac 100644 (file)
@@ -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 (file)
index 0000000..808f5af
--- /dev/null
@@ -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 <artursz@iafrica.com>                   *
+ *                  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 <artursz@iafrica.com>
+ * @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 <stdio.h>
+#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<AliHLTTriggerDecision*>(file->Get("MuonSpectroTrigger;1"));
+       scalars = dynamic_cast<AliHLTMuonSpectroScalars*>(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<AliHLTTriggerDecision*>(file->Get("MuonSpectroTrigger;2"));
+       scalars = dynamic_cast<AliHLTMuonSpectroScalars*>(file->Get("AliHLTMuonSpectroScalars;2"));
+       result = Check(1, decision, scalars, true, domainMUON, "Dimuon in muon spectrometer", scalarsEvent1);
+       if (! result) goto cleanup;
+       decision = dynamic_cast<AliHLTTriggerDecision*>(file->Get("MuonSpectroTrigger;3"));
+       scalars = dynamic_cast<AliHLTMuonSpectroScalars*>(file->Get("AliHLTMuonSpectroScalars;3"));
+       result = Check(2, decision, scalars, true, domainMUON, "Dimuon in muon spectrometer", scalarsEvent2);
+       if (! result) goto cleanup;
+       decision = dynamic_cast<AliHLTTriggerDecision*>(file->Get("MuonSpectroTrigger;4"));
+       scalars = dynamic_cast<AliHLTMuonSpectroScalars*>(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<AliHLTTriggerDecision*>(file->Get("MuonSpectroTrigger;5"));
+       scalars = dynamic_cast<AliHLTMuonSpectroScalars*>(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 (file)
index 0000000..ebb28e4
Binary files /dev/null and b/OCDB/HLT/ConfigHLT/HLTGlobalTrigger/Run0_999999999_v0_s2.root differ