Fixes to trigger reconstruction component to handle real data better.
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 20 Nov 2009 13:53:08 +0000 (13:53 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 20 Nov 2009 13:53:08 +0000 (13:53 +0000)
AliHLTMUONTriggerReconstructorComponent now also generates optional debug data blocks and AliHLTMUONRootifierComponent fills the data into the rootified objects.
Also fixed up some of the printing and documentation in the dHLT ROOT objects.

18 files changed:
HLT/MUON/AliHLTMUONDecision.cxx
HLT/MUON/AliHLTMUONMansoTrack.h
HLT/MUON/AliHLTMUONRecHit.cxx
HLT/MUON/AliHLTMUONRecHit.h
HLT/MUON/AliHLTMUONTrigRecsDebugBlockStruct.cxx
HLT/MUON/AliHLTMUONTrigRecsDebugBlockStruct.h
HLT/MUON/AliHLTMUONTriggerRecord.cxx
HLT/MUON/AliHLTMUONTriggerRecord.h
HLT/MUON/AliHLTMUONUtils.h
HLT/MUON/OfflineInterface/AliHLTMUONRootifierComponent.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONCalculations.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONCalculations.h
HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructor.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructor.h
HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructorComponent.cxx
HLT/MUON/OnlineAnalysis/AliHLTMUONTriggerReconstructorComponent.h
HLT/MUON/macros/RunChain.C
HLT/MUON/utils/dHLTdumpraw.cxx

index 351ccd1..5d74624 100644 (file)
@@ -296,6 +296,7 @@ void AliHLTMUONDecision::Print(Option_t* option) const
                        if (decision == NULL) continue;
                        decision->Print("all");
                }
+               if (NumberOfTracks() == 0) cout << "(None)" << endl;
                cout << "===============================================" << endl;
                cout << "========== Triggers for track pairs: ==========" << endl;
                for (Int_t j = 0; j < NumberOfPairs(); j++)
@@ -304,6 +305,7 @@ void AliHLTMUONDecision::Print(Option_t* option) const
                        if (decision == NULL) continue;
                        decision->Print("all");
                }
+               if (NumberOfPairs() == 0) cout << "(None)" << endl;
        }
        else
        {
index 65587d4..2877dbb 100644 (file)
@@ -170,6 +170,18 @@ public:
        {
                return not this->operator == (track);
        }
+       
+       /**
+        * Returns the Z coordinate in the middle of the magnetic field used to
+        * calculate the momentum.
+        */
+       Float_t Zmiddle() const { return fZmiddle; }
+       
+       /**
+        * Returns the integrated magnetic field strength times polarity used in
+        * the calculation of the momentum. Value returned in (T.m) tesla metres.
+        */
+       Float_t QBL() const { return fQBL; }
 
 private:
 
@@ -189,9 +201,9 @@ private:
        
        // Parameters used in momentum estimation:
        Float_t fZmiddle; ///< Particle momentum X component in GeV/c.
-       Float_t fQBL;     ///< The integrated magnetic field times charge in (T.m) tesla metres.
+       Float_t fQBL;     ///< The integrated magnetic field times the field polarity in (T.m) tesla metres.
 
-       ClassDef(AliHLTMUONMansoTrack, 3); // Manso track object containing data converted from a dHLT internal track structure.
+       ClassDef(AliHLTMUONMansoTrack, 4); // Manso track object containing data converted from a dHLT internal track structure.
 };
 
 #endif // ALIHLTMUONMANSOTRACK_H
index a4fe521..fa702d3 100644 (file)
@@ -94,18 +94,19 @@ Int_t AliHLTMUONRecHit::Chamber(bool warn) const
 
 
 void AliHLTMUONRecHit::AddChannel(
-               Short_t manu, Short_t channel, Short_t signal,
+               Short_t buspatch, Short_t manu, Short_t channel, Short_t signal,
                UInt_t rawDataWord
        )
 {
 /// Adds a new channel to the channels list forming this hit's cluster.
+/// @param buspatch  The bus patch ID of the channel.
 /// @param manu    The MANU number
 /// @param channel The MANU channel address.
 /// @param signal  The ADC signal value measured on the channel.
 /// @param rawDataWord This is the raw data word as read from the DDL.
 
        Int_t index = fChannels.GetEntriesFast();
-       new (fChannels[index]) AliChannel(manu, channel, signal, rawDataWord);
+       new (fChannels[index]) AliChannel(buspatch, manu, channel, signal, rawDataWord);
 }
 
 
@@ -137,23 +138,23 @@ void AliHLTMUONRecHit::Print(Option_t* option) const
        }
        else if (strcmp(option, "all") == 0)
        {
-               cout << "(x = " << X() << " cm, y = " << Y()
+               streamsize w = cout.width();
+               ios::fmtflags f = cout.flags();
+               cout << "RecHit: (x = " << X() << " cm, y = " << Y()
                        << " cm, z = " << Z()
                        << " cm); source DDL = " << fSourceDDL
                        << "; DetElemID = " << fDetElemId
                        << "; cluster ID = " << fClusterId
-                       << "; charge (Bending, Non-bending) = (" << fChargeB
-                       << ", " << fChargeNB
-                       << "); expected #ch (Bending, Non-bending) = ("
-                       << fNchExpB << ", " << fNchExpNB << ")" << endl;
+                       << endl;
+               cout << setw(0) << "              Plane:" << setw(14) << "Bending" << setw(14) << "Non-bending" << endl;
+               cout << setw(0) << "             Charge:" << setw(14) << fChargeB << setw(14) << fChargeNB << endl;
+               cout << setw(0) << "Expected channels #:" << setw(14) << fNchExpB << setw(14) << fNchExpNB << setw(0) << endl;
                if (fChannels.GetEntriesFast() == 0)
                {
                        cout << "No channels found for this hit." << endl;
                }
                else
                {
-                       streamsize w = cout.width();
-                       ios::fmtflags f = cout.flags();
                        cout << setw(12) << "MANU"
                                << setw(12) << "Channel"
                                << setw(12) << "Signal"
@@ -171,9 +172,9 @@ void AliHLTMUONRecHit::Print(Option_t* option) const
                                cout << c->RawDataWord() << right << endl;
                                cout.fill(fc);
                        }
-                       cout.width(w); // reset the field width to previous value.
-                       cout.flags(f); // reset the flags to previous values.
                }
+               cout.width(w); // reset the field width to previous value.
+               cout.flags(f); // reset the flags to previous values.
        }
        else
        {
index e249d93..6e9eb89 100644 (file)
@@ -298,14 +298,15 @@ public:
        
        /**
         * Adds a new channel to this hit if it is on a tracking chamber.
+        * @param buspatch  The bus patch ID of the channel.
         * @param manu    The MANU number
         * @param channel The MANU channel address.
         * @param signal  The ADC signal value measured on the channel.
         * @param rawDataWord This is the raw data word as read from the DDL.
         */
        void AddChannel(
-                       Short_t manu, Short_t channel, Short_t signal,
-                       UInt_t rawDataWord
+                       Short_t buspatch, Short_t manu, Short_t channel,
+                       Short_t signal, UInt_t rawDataWord
                );
 
        /**
index 880c956..dfafb7f 100644 (file)
@@ -44,6 +44,20 @@ std::ostream& operator << (
                << ", fY2Y1 = " << info.fL0Struct.fY2Y1
                << ", fY4Y3 = " << info.fL0Struct.fY4Y3
                << ", fTriggerBits = " << info.fL0Struct.fTriggerBits
+               << std::dec << "}"
+               << ", fL0StructPrev = {fX2X1 = " << std::showbase << std::hex
+               << info.fL0StructPrev.fX2X1
+               << ", fX4X3 = " << info.fL0StructPrev.fX4X3
+               << ", fY2Y1 = " << info.fL0StructPrev.fY2Y1
+               << ", fY4Y3 = " << info.fL0StructPrev.fY4Y3
+               << ", fTriggerBits = " << info.fL0StructPrev.fTriggerBits
+               << std::dec << "}"
+               << ", fL0StructNext = {fX2X1 = " << std::showbase << std::hex
+               << info.fL0StructNext.fX2X1
+               << ", fX4X3 = " << info.fL0StructNext.fX4X3
+               << ", fY2Y1 = " << info.fL0StructNext.fY2Y1
+               << ", fY4Y3 = " << info.fL0StructNext.fY4Y3
+               << ", fTriggerBits = " << info.fL0StructNext.fTriggerBits
                << std::dec << "}}";
        return stream;
 }
@@ -68,6 +82,31 @@ std::ostream& operator << (
 
 
 bool operator == (
+               const AliHLTMUONTrigRecInfoStruct& a,
+               const AliHLTMUONTrigRecInfoStruct& b
+       )
+{
+       return a.fTrigRecId == b.fTrigRecId and a.fDetElemId == b.fDetElemId
+               and a.fZmiddle == b.fZmiddle and a.fBl == b.fBl
+               and a.fL0Struct.fX2X1 == b.fL0Struct.fX2X1
+               and a.fL0Struct.fX4X3 == b.fL0Struct.fX4X3
+               and a.fL0Struct.fY2Y1 == b.fL0Struct.fY2Y1
+               and a.fL0Struct.fY4Y3 == b.fL0Struct.fY4Y3
+               and a.fL0Struct.fTriggerBits == b.fL0Struct.fTriggerBits
+               and a.fL0StructPrev.fX2X1 == b.fL0StructPrev.fX2X1
+               and a.fL0StructPrev.fX4X3 == b.fL0StructPrev.fX4X3
+               and a.fL0StructPrev.fY2Y1 == b.fL0StructPrev.fY2Y1
+               and a.fL0StructPrev.fY4Y3 == b.fL0StructPrev.fY4Y3
+               and a.fL0StructPrev.fTriggerBits == b.fL0StructPrev.fTriggerBits
+               and a.fL0StructNext.fX2X1 == b.fL0StructNext.fX2X1
+               and a.fL0StructNext.fX4X3 == b.fL0StructNext.fX4X3
+               and a.fL0StructNext.fY2Y1 == b.fL0StructNext.fY2Y1
+               and a.fL0StructNext.fY4Y3 == b.fL0StructNext.fY4Y3
+               and a.fL0StructNext.fTriggerBits == b.fL0StructNext.fTriggerBits;
+}
+
+
+bool operator == (
                const AliHLTMUONTrigRecsDebugBlockStruct& a,
                const AliHLTMUONTrigRecsDebugBlockStruct& b
        )
index c4a779a..cd58589 100644 (file)
@@ -41,6 +41,8 @@ struct AliHLTMUONTrigRecInfoStruct
        AliHLTFloat32_t fBl; // The integrated magnetic field in (T.m) tesla metres.
        
        AliMUONLocalInfoStruct fL0Struct;  // Copy of the L0 local trigger structure bits.
+       AliMUONLocalInfoStruct fL0StructPrev;  // Copy of the previous L0 local trigger structure bits used. Can be zero if none used.
+       AliMUONLocalInfoStruct fL0StructNext;  // Copy of the next L0 local trigger structure bits used. Can be zero if none used.
 };
 
 /**
@@ -77,19 +79,10 @@ std::ostream& operator << (
        );
 
 
-inline bool operator == (
+bool operator == (
                const AliHLTMUONTrigRecInfoStruct& a,
                const AliHLTMUONTrigRecInfoStruct& b
-       )
-{
-       return a.fTrigRecId == b.fTrigRecId and a.fDetElemId == b.fDetElemId
-               and a.fZmiddle == b.fZmiddle and a.fBl == b.fBl
-               and a.fL0Struct.fX2X1 == b.fL0Struct.fX2X1
-               and a.fL0Struct.fX4X3 == b.fL0Struct.fX4X3
-               and a.fL0Struct.fY2Y1 == b.fL0Struct.fY2Y1
-               and a.fL0Struct.fY4Y3 == b.fL0Struct.fY4Y3
-               and a.fL0Struct.fTriggerBits == b.fL0Struct.fTriggerBits;
-}
+       );
 
 inline bool operator != (
                const AliHLTMUONTrigRecInfoStruct& a,
index 126b293..812f83c 100644 (file)
@@ -93,8 +93,11 @@ AliHLTMUONTriggerRecord::AliHLTMUONTriggerRecord(
        for (int i = 0; i < 4; i++)
        {
                fDetElemId[i] = -1;
-               fPatternX[i] = -1;
-               fPatternY[i] = -1;
+               for (int j = 0; j < 3; j++)
+               {
+                       fPatternX[i][j] = -1;
+                       fPatternY[i][j] = -1;
+               }
        }
 }
 
@@ -134,37 +137,63 @@ Int_t AliHLTMUONTriggerRecord::DetElemId(Int_t chamber) const
 }
 
 
-Int_t AliHLTMUONTriggerRecord::PatternX(Int_t chamber) const
+Int_t AliHLTMUONTriggerRecord::PatternX(Int_t chamber, Int_t board) const
 {
 /// Returns the raw data X pattern of the hit on the specified chamber.
 /// \param chamber  The chamber for which to fetch the bit pattern.
 ///                 Valid values are in the range [11..14].
+/// \param board  The board for which to fetch the bit pattern in the range [0..2].
+///               0 indicates the previous board, 1 the central and 2 the next board.
 /// \returns X bit pattern of the hit.
 
-       if (11 <= chamber and chamber <= 14) return fPatternX[chamber - 11];
+       if (chamber < 11 or 14 < chamber)
+       {
+               AliError(Form(
+                       "Chamber number %d is not in the valid range [11..14].",
+                       int(chamber)
+               ));
+               return 0;
+       }
+       if (board < 0 or 2 < board)
+       {
+               AliError(Form(
+                       "Board number %d is not in the valid range [0..2].",
+                       int(board)
+               ));
+               return 0;
+       }
        
-       AliError(Form(
-               "Chamber number %d is not in the valid range [11..14].",
-               int(chamber)
-       ));
-       return fPatternX[0];
+       return fPatternX[chamber - 11][board];
 }
 
 
-Int_t AliHLTMUONTriggerRecord::PatternY(Int_t chamber) const
+Int_t AliHLTMUONTriggerRecord::PatternY(Int_t chamber, Int_t board) const
 {
 /// Returns the raw data Y pattern of the hit on the specified chamber.
 /// \param chamber  The chamber for which to fetch the bit pattern.
 ///                 Valid values are in the range [11..14].
+/// \param board  The board for which to fetch the bit pattern in the range [0..2].
+///               0 indicates the previous board, 1 the central and 2 the next board.
 /// \returns Y bit pattern of the hit.
 
-       if (11 <= chamber and chamber <= 14) return fPatternY[chamber - 11];
+       if (chamber < 11 or 14 < chamber)
+       {
+               AliError(Form(
+                       "Chamber number %d is not in the valid range [11..14].",
+                       int(chamber)
+               ));
+               return 0;
+       }
+       if (board < 0 or 2 < board)
+       {
+               AliError(Form(
+                       "Board number %d is not in the valid range [0..2].",
+                       int(board)
+               ));
+               return 0;
+       }
        
-       AliError(Form(
-               "Chamber number %d is not in the valid range [11..14].",
-               int(chamber)
-       ));
-       return fPatternY[0];
+       return fPatternY[chamber - 11][board];
 }
 
 
@@ -191,9 +220,27 @@ void AliHLTMUONTriggerRecord::SetHit(Int_t chamber, Float_t x, Float_t y, Float_
 }
 
 
+void AliHLTMUONTriggerRecord::SetHit(Int_t chamber, Float_t x, Float_t y, Float_t z, Int_t detElemId)
+{
+       // Sets the hit with the detection element ID.
+       
+       if (11 <= chamber and chamber <= 14)
+       {
+               fHit[chamber - 11].SetXYZ(x, y, z);
+               fDetElemId[chamber - 11] = detElemId;
+       }
+       else
+       {
+               AliError(Form(
+                       "Chamber number %d is not in the valid range [11..14].",
+                       int(chamber)
+               ));
+       }
+}
+
+
 void AliHLTMUONTriggerRecord::SetHitDebugInfo(
-               Int_t chamber,
-               Int_t detElemId, UShort_t patternX, UShort_t patternY
+               Int_t chamber, UShort_t patternX[3], UShort_t patternY[3]
        )
 {
 /// Fills the debugging information corresponding to the hit on the specified chamber.
@@ -201,14 +248,16 @@ void AliHLTMUONTriggerRecord::SetHitDebugInfo(
 /// @param chamber  The chamber for which to set the debugging information.
 ///                Valid values are in the range [11..14].
 /// @param detElemId  The detector element ID.
-/// @param patterX    The X bit pattern from the local board.
-/// @param patterY    The Y bit pattern from the local board.
+/// @param patternX    The X bit patterns from the local board.
+/// @param patternY    The Y bit patterns from the local board.
 
        if (11 <= chamber and chamber <= 14)
        {
-               fDetElemId[chamber - 11] = detElemId;
-               fPatternX[chamber - 11] = patternX;
-               fPatternY[chamber - 11] = patternY;
+               for (int i = 0; i < 3; i++)
+               {
+                       fPatternX[chamber - 11][i] = patternX[i];
+                       fPatternY[chamber - 11][i] = patternY[i];
+               }
        }
        else
        {
@@ -220,6 +269,15 @@ void AliHLTMUONTriggerRecord::SetHitDebugInfo(
 }
 
 
+void AliHLTMUONTriggerRecord::SetDebugInfo(Float_t zmiddle, Float_t bfieldintegral)
+{
+       // Sets the trigger record debug information.
+       
+       fZmiddle = zmiddle;
+       fQBL = bfieldintegral;
+}
+
+
 void AliHLTMUONTriggerRecord::Print(Option_t* option) const
 {
 /// Prints the trigger record to standard output (screen).
@@ -270,37 +328,58 @@ void AliHLTMUONTriggerRecord::Print(Option_t* option) const
                        << setw(8) << "X (cm)"
                        << setw(12) << "Y (cm)"
                        << setw(12) << "Z (cm)"
-                       << setw(12) << "DetElemID"
-                       << setw(18) << "X bit pattern"
-                       << setw(18) << "Y bit pattern" << endl;
+                       << setw(12) << "DetElemID" << endl;
                for (int i = 0; i < 4; i++)
                {
                        cout << setw(9) << i+11
                                << setw(14) << fHit[i].X()
                                << setw(12) << fHit[i].Y()
                                << setw(12) << fHit[i].Z()
-                               << setw(12) << fDetElemId[i];
-                       if (fPatternX[i] != -1)
-                       {
-                               // Print the X pattern as a bit pattern.
-                               cout << "  ";
-                               for (Int_t j = 15; j >= 0; j--)
-                                       cout << (((fPatternX[i] & (1 << j)) > 0) ? "1" : "0");
-                       }
-                       else
-                       {
-                               cout << "  ----------------";
-                       }
-                       if (fPatternY[i] != -1)
+                               << setw(12) << fDetElemId[i]
+                               << endl;
+               }
+               cout << setw(9) << "Chamber"
+                       << setw(18+17*2) << "X bit patterns for local boards"
+                       << setw(18+17*2) << "Y bit patterns for local boards"
+                       << endl;
+               cout << setw(9+18) << "Next"
+                       << setw(17) << "Central"
+                       << setw(17) << "Previous"
+                       << setw(18) << "Next"
+                       << setw(17) << "Central"
+                       << setw(17) << "Previous"
+                       << endl;
+               for (int i = 0; i < 4; i++)
+               {
+                       cout << setw(9) << i+11 << "  ";
+                       for (int k = 0; k < 3; ++k)
                        {
-                               // Print the Y pattern as a bit pattern.
-                               cout << "  ";
-                               for (Int_t j = 15; j >= 0; j--)
-                                       cout << (((fPatternY[i] & (1 << j)) > 0) ? "1" : "0");
+                               if (k != 0) cout << "|";
+                               if (fPatternX[i][2-k] != -1)
+                               {
+                                       // Print the X pattern as a bit pattern.
+                                       for (Int_t j = 15; j >= 0; j--)
+                                               cout << (((fPatternX[i][2-k] & (1 << j)) > 0) ? "1" : "0");
+                               }
+                               else
+                               {
+                                       cout << "----------------";
+                               }
                        }
-                       else
+                       cout << "  ";
+                       for (int k = 0; k < 3; ++k)
                        {
-                               cout << "  ----------------";
+                               if (k != 0) cout << "|";
+                               if (fPatternY[i][2-k] != -1)
+                               {
+                                       // Print the Y pattern as a bit pattern.
+                                       for (Int_t j = 15; j >= 0; j--)
+                                               cout << (((fPatternY[i][2-k] & (1 << j)) > 0) ? "1" : "0");
+                               }
+                               else
+                               {
+                                       cout << "----------------";
+                               }
                        }
                        cout << endl;
                }
index 500d944..b799b82 100644 (file)
@@ -164,16 +164,20 @@ public:
         * -1 is returned if this information was not set.
         * @param chamber  The chamber for which to fetch the bit pattern.
         *                 Valid values are in the range [11..14].
+        * \param board  The board for which to fetch the bit pattern in the range [0..2].
+        *             0 indicates the previous board, 1 the central and 2 the next board.
         */
-       Int_t PatternX(Int_t chamber) const;
+       Int_t PatternX(Int_t chamber, Int_t board) const;
        
        /**
         * Returns the 16 bit Y pattern from the local board.
         * -1 is returned if this information was not set.
         * @param chamber  The chamber for which to fetch the bit pattern.
         *                Valid values are in the range [11..14].
+        * \param board  The board for which to fetch the bit pattern in the range [0..2].
+        *             0 indicates the previous board, 1 the central and 2 the next board.
         */
-       Int_t PatternY(Int_t chamber) const;
+       Int_t PatternY(Int_t chamber, Int_t board) const;
        
        /**
         * Returns the Z coordinate in the middle of the magnetic field used to
@@ -182,7 +186,7 @@ public:
        Float_t Zmiddle() const { return fZmiddle; }
        
        /**
-        * Returns the integrated magnetic field strength times charge used in
+        * Returns the integrated magnetic field strength times polarity used in
         * the calculation of the momentum. Value returned in (T.m) tesla metres.
         */
        Float_t QBL() const { return fQBL; }
@@ -199,17 +203,32 @@ public:
        void SetHit(Int_t chamber, Float_t x, Float_t y, Float_t z);
        
        /**
+        * Sets the hit coordinate on a given chamber with the detection element ID.
+        * @param chamber  The chamber for which to set the hit. Valid values
+        *                 are in the range [11..14].
+        * @param x  The X coordinate of the hit in centimetres.
+        * @param y  The Y coordinate of the hit in centimetres.
+        * @param z  The Z coordinate of the hit in centimetres.
+        * @param detElemId The detection element ID where the hit was found.
+        */
+       void SetHit(Int_t chamber, Float_t x, Float_t y, Float_t z, Int_t detElemId);
+       
+       /**
         * Sets the debugging information for the hit on the specified chamber.
         * @param chamber  The chamber for which to set the debugging information.
         *                Valid values are in the range [11..14].
-        * @param detElemId  The detector element ID.
-        * @param patterX    The X bit pattern from the local board.
-        * @param patterY    The Y bit pattern from the local board.
+        * @param patternX  Array of X bit pattern from the local boards.
+        * @param patternY  Array of Y bit pattern from the local boards.
+        * \note The bit patterns in the array are in the order: [previous, central, next].
         */
-       void SetHitDebugInfo(
-                       Int_t chamber,
-                       Int_t detElemId, UShort_t patternX, UShort_t patternY
-               );
+       void SetHitDebugInfo(Int_t chamber, UShort_t patternX[3], UShort_t patternY[3]);
+       
+       /**
+        * Sets the debugging information for the hit on the specified chamber.
+        * @param zmiddle  The z coordinate of the middle of the magnetic field.
+        * @param bfieldintegral  The magnetic field integral times field polarity.
+        */
+       void SetDebugInfo(Float_t zmiddle, Float_t bfieldintegral);
        
        /**
         * Prints the details of the trigger record.
@@ -247,14 +266,14 @@ private:
        // dHLT components were not set to produce this information.
        Int_t fSourceDDL;  ///< The DDL from which this trigger record originates.
        Int_t fDetElemId[4]; ///< The detector element ID for the hit on each chamber 11 to 14.
-       Int_t fPatternX[4];  ///< The X pattern from the local board structure for chambers 11 to 14. -1 if invalid.
-       Int_t fPatternY[4];  ///< The Y pattern from the local board structure for chambers 11 to 14. -1 if invalid.
+       Int_t fPatternX[4][3]; ///< The X strip pattern for chambers 11 to 14 and previous, central and next local boards. -1 if invalid.
+       Int_t fPatternY[4][3]; ///< The Y strip pattern for chambers 11 to 14 and previous, central and next local boards. -1 if invalid.
        
        // Parameters used in momentum estimation:
        Float_t fZmiddle; ///< Particle momentum X component in GeV/c.
-       Float_t fQBL;     ///< The integrated magnetic field times charge in (T.m) tesla metres.
+       Float_t fQBL;     ///< The integrated magnetic field times field polarity in (T.m) tesla metres.
                
-       ClassDef(AliHLTMUONTriggerRecord, 3);  // Trigger record object translated from dHLT internal raw data.
+       ClassDef(AliHLTMUONTriggerRecord, 4);  // Trigger record object translated from dHLT internal raw data.
 };
 
 #endif // ALIHLTMUONTRIGGERRECORD_H
index 6f18626..ba9e476 100644 (file)
@@ -98,6 +98,15 @@ public:
                );
 
        /**
+        * Returns the detector element ID from the flags bits.
+        * [in]  @param flags  The flags from an AliHLTMUONRecHitStruct structure.
+        */
+       static AliHLTUInt16_t GetDetElemIdFromFlags(AliHLTUInt32_t flags)
+       {
+               return flags & 0xFFF;
+       }
+
+       /**
         * This packs the given parameters into the bits of a word appropriate
         * for AliHLTMUONMansoTrackStruct::fFlags.
         * @param sign    The particle sign.
index 1b22e63..c3120ab 100644 (file)
 #include "AliHLTMUONTriggerRecord.h"
 #include "AliHLTMUONMansoTrack.h"
 #include "AliHLTMUONDecision.h"
+#include "AliMUONTriggerDDLDecoderEventHandler.h"
 #include "TClonesArray.h"
 #include <cassert>
+#include <map>
 
 ClassImp(AliHLTMUONRootifierComponent);
 
@@ -192,6 +194,7 @@ int AliHLTMUONRootifierComponent::DoEvent(
        AliHLTMUONEvent event(evtData.fEventID);
        const AliHLTComponentBlockData* block = NULL;
        AliHLTUInt32_t specification = 0;  // Contains the output data block spec bits.
+       std::map<AliHLTInt32_t, AliHLTMUONTriggerRecord*> triggerMap;
 
        // First process the blocks of reconstructed hits and trigger records.
        for (int i = 0; i < GetNumberOfInputBlocks(); i++)
@@ -302,13 +305,21 @@ int AliHLTMUONRootifierComponent::DoEvent(
                                                t.fId, sign, t.fPx, t.fPy, t.fPz, sourceDDL
                                        );
                                for (int k = 0; k < 4; k++)
-                                       tr->SetHit(k+11, t.fHit[k].fX, t.fHit[k].fY, t.fHit[k].fZ);
+                               {
+                                       Int_t detElemId = AliHLTMUONUtils::GetDetElemIdFromFlags(t.fHit[k].fFlags);
+                                       tr->SetHit(k+11, t.fHit[k].fX, t.fHit[k].fY, t.fHit[k].fZ, detElemId);
+                               }
                                event.Add(tr);
+                               triggerMap[t.fId] = tr;
                        }
                }
                else
                {
-                       if (block->fDataType != AliHLTMUONConstants::MansoTracksBlockDataType() and
+                       if (block->fDataType != AliHLTMUONConstants::TrigRecsDebugBlockDataType() and
+                           block->fDataType != AliHLTMUONConstants::ClusterBlockDataType() and
+                           block->fDataType != AliHLTMUONConstants::ChannelBlockDataType() and
+                           block->fDataType != AliHLTMUONConstants::MansoTracksBlockDataType() and
+                           block->fDataType != AliHLTMUONConstants::MansoCandidatesBlockDataType() and
                            block->fDataType != AliHLTMUONConstants::SinglesDecisionBlockDataType() and
                            block->fDataType != AliHLTMUONConstants::PairsDecisionBlockDataType()
                           )
@@ -329,6 +340,124 @@ int AliHLTMUONRootifierComponent::DoEvent(
                }
        }
        
+       // We need to check if there are any trigger record debug data blocks
+       // and add their information to the AliHLTMUONTriggerRecord objects.
+       for (block = GetFirstInputBlock(AliHLTMUONConstants::TrigRecsDebugBlockDataType());
+            block != NULL;
+            block = GetNextInputBlock()
+           )
+       {
+               specification |= block->fSpecification;
+               AliHLTMUONTrigRecsDebugBlockReader inblock(block->fPtr, block->fSize);
+               if (not BlockStructureOk(inblock))
+               {
+                       if (DumpDataOnError()) DumpEvent(evtData, trigData);
+                       continue;
+               }
+               
+               for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
+               {
+                       const AliHLTMUONTrigRecInfoStruct& triginfo = inblock[n];
+                       
+                       AliHLTMUONTriggerRecord* trigrec = triggerMap[triginfo.fTrigRecId];
+                       if (trigrec == NULL)
+                       {
+                               // Decode the source DDL from the specification bits.
+                               Int_t sourceDDL = -1;
+                               bool ddl[22];
+                               AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
+                               for (int k = 0; k < 22; k++)
+                               {
+                                       if (ddl[k])
+                                       {
+                                               if (sourceDDL == -1)
+                                               {
+                                                       sourceDDL = k+1;
+                                               }
+                                               else
+                                               {
+                                                       HLTWarning("An trigger debug information data block"
+                                                               " contains data from multiple DDL sources."
+                                                       );
+                                               }
+                                       }
+                               }
+                               if (sourceDDL != -1 and (sourceDDL < 21 or sourceDDL > 22))
+                               {
+                                       HLTWarning("The source DDL for a trigger debug information data"
+                                               " block is %d. The expected range for the DDL is [21..22].",
+                                               sourceDDL
+                                       );
+                               }
+                               
+                               trigrec = new AliHLTMUONTriggerRecord(
+                                               0, 0, 0, 0, 0, sourceDDL
+                                       );
+                       }
+                       
+                       for (Int_t j = 0; j < 4; ++j)
+                       {
+                               if (triginfo.fDetElemId[j] != trigrec->DetElemId(j+11))
+                               {
+                                       HLTWarning("Found a trigger record with a hit on chamber %d with a different"
+                                               " detector element ID %d than the debug information %d.",
+                                               j, trigrec->DetElemId(j+11), triginfo.fDetElemId[j]
+                                       );
+                               }
+                       }
+                       
+                       typedef AliMUONTriggerDDLDecoderEventHandler Handler;
+                       
+                       trigrec->SetDebugInfo(triginfo.fZmiddle, triginfo.fBl);
+                       
+                       UShort_t patternX[4][3] = {
+                               {
+                                       Handler::GetLocalX1(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalX1(&triginfo.fL0Struct),
+                                       Handler::GetLocalX1(&triginfo.fL0StructNext)
+                               },{
+                                       Handler::GetLocalX2(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalX2(&triginfo.fL0Struct),
+                                       Handler::GetLocalX2(&triginfo.fL0StructNext)
+                               },{
+                                       Handler::GetLocalX3(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalX3(&triginfo.fL0Struct),
+                                       Handler::GetLocalX3(&triginfo.fL0StructNext)
+                               },{
+                                       Handler::GetLocalX4(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalX4(&triginfo.fL0Struct),
+                                       Handler::GetLocalX4(&triginfo.fL0StructNext)
+                               }
+                       };
+                       UShort_t patternY[4][3] = {
+                               {
+                                       Handler::GetLocalY1(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalY1(&triginfo.fL0Struct),
+                                       Handler::GetLocalY1(&triginfo.fL0StructNext)
+                               },{
+                                       Handler::GetLocalY2(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalY2(&triginfo.fL0Struct),
+                                       Handler::GetLocalY2(&triginfo.fL0StructNext)
+                               },{
+                                       Handler::GetLocalY3(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalY3(&triginfo.fL0Struct),
+                                       Handler::GetLocalY3(&triginfo.fL0StructNext)
+                               },{
+                                       Handler::GetLocalY4(&triginfo.fL0StructPrev),
+                                       Handler::GetLocalY4(&triginfo.fL0Struct),
+                                       Handler::GetLocalY4(&triginfo.fL0StructNext)
+                               }
+                       };
+                       
+                       for (Int_t j = 0; j < 4; ++j)
+                       {
+                               trigrec->SetHitDebugInfo(j+11, patternX[j], patternY[j]);
+                       }
+               }
+       }
+       
+       std::map<AliHLTInt32_t, AliHLTMUONRecHit*> clusterMap;
+       
        // We need to check if there are any cluster data blocks and add their
        // information to the AliHLTMUONRecHit objects.
        for (block = GetFirstInputBlock(AliHLTMUONConstants::ClusterBlockDataType());
@@ -407,10 +536,11 @@ int AliHLTMUONRootifierComponent::DoEvent(
                                                sourceDDL
                                        );
                                }
-                               event.Add(new AliHLTMUONRecHit(
+                               hit = new AliHLTMUONRecHit(
                                                clust.fHit.fX, clust.fHit.fY, clust.fHit.fZ,
                                                sourceDDL, detElemId
-                                       ));
+                                       );
+                               event.Add(hit);
                        }
                        else
                        {
@@ -421,6 +551,69 @@ int AliHLTMUONRootifierComponent::DoEvent(
                                                  hit->SourceDDL()
                                );
                        }
+                       
+                       clusterMap[clust.fId] = hit;
+               }
+       }
+       
+       // We need to check if there are any channel data blocks and add their
+       // information to the AliHLTMUONRecHit objects.
+       for (block = GetFirstInputBlock(AliHLTMUONConstants::ChannelBlockDataType());
+            block != NULL;
+            block = GetNextInputBlock()
+           )
+       {
+               specification |= block->fSpecification;
+               AliHLTMUONChannelsBlockReader inblock(block->fPtr, block->fSize);
+               if (not BlockStructureOk(inblock))
+               {
+                       if (DumpDataOnError()) DumpEvent(evtData, trigData);
+                       continue;
+               }
+               
+               for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
+               {
+                       const AliHLTMUONChannelStruct& channel = inblock[n];
+                       
+                       AliHLTMUONRecHit* hit = clusterMap[channel.fClusterId];
+                       if (hit == NULL)
+                       {
+                               // Decode the source DDL from the specification bits.
+                               Int_t sourceDDL = -1;
+                               bool ddl[22];
+                               AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
+                               for (int k = 0; k < 22; k++)
+                               {
+                                       if (ddl[k])
+                                       {
+                                               if (sourceDDL == -1)
+                                               {
+                                                       sourceDDL = k+1;
+                                               }
+                                               else
+                                               {
+                                                       HLTWarning("An input block of cluster data contains"
+                                                               " data from multiple DDL sources."
+                                                       );
+                                               }
+                                       }
+                               }
+                               if (sourceDDL > 20)
+                               {
+                                       HLTWarning("The source DDL of a cluster data input block is %d."
+                                               " The expected range for the DDL is [1..20].",
+                                               sourceDDL
+                                       );
+                               }
+                               hit = new AliHLTMUONRecHit(0, 0, 0, sourceDDL, -1);
+                               event.Add(hit);
+                       }
+                       
+                       hit->AddChannel(
+                                       channel.fBusPatch, channel.fManu,
+                                       channel.fChannelAddress, channel.fSignal,
+                                       channel.fRawDataWord
+                               );
                }
        }
        
@@ -675,7 +868,6 @@ int AliHLTMUONRootifierComponent::DoEvent(
                }
        }
        
-       
        // Do not add the decision if no decision blocks were found.
        if (decisionBlockFound)
        {
index e1c1f18..96e698c 100644 (file)
@@ -315,6 +315,50 @@ bool AliHLTMUONCalculations::FitLineToData(
 }
 
 
+bool AliHLTMUONCalculations::FitLineToData(
+               const AliHLTFloat32_t* x, const AliHLTFloat32_t* z, AliHLTUInt32_t n
+       )
+{
+       /// A straight line is fitted in the X, Z data points using a least squares fit.
+       /// http://mathworld.wolfram.com/LeastSquaresFitting.html
+       /// If this method returns true, then the fitted parameters can fetched using the
+       /// method calls Mzx() and Czx(). The line is then given by: x = Mzx() * z + Czx()
+       /// \param x  This must point to the array of x data values.
+       /// \param z  This must point to the array of z data values.
+       /// \param n  Specifies the number of data points in the x and z arrays.
+       /// \return  true if the line could be fitted or false otherwise.
+       ///     The reason for failure could be either too few data points or the slopes
+       ///     Mzx() would be infinite, implying a line that is perpendicular to the z axis.
+       
+       if (n < 2) return false;
+       
+       AliHLTFloat32_t sumX = 0;
+       AliHLTFloat32_t sumZ = 0;
+       for (AliHLTUInt32_t i = 0; i < n; i++)
+       {
+               sumX += x[i];
+               sumZ += z[i];
+       }
+       AliHLTFloat32_t meanX = sumX / AliHLTFloat32_t(n);
+       AliHLTFloat32_t meanZ = sumZ / AliHLTFloat32_t(n);
+       
+       AliHLTFloat32_t vSSzz = 0;
+       AliHLTFloat32_t vSSzx = 0;
+       for (AliHLTUInt32_t i = 0; i < n; i++)
+       {
+               vSSzz += (z[i] - meanZ)*(z[i] - meanZ);
+               vSSzx += (z[i] - meanZ)*(x[i] - meanX);
+       }
+       
+       // Calculate params for line x = fgMzx * z + fgCzx.
+       if (vSSzz == 0) return false;
+       fgMzx = vSSzx / vSSzz;
+       fgCzx = meanX - fgMzx * meanZ;
+       
+       return true;
+}
+
+
 AliHLTFloat32_t AliHLTMUONCalculations::AliHLTMUONCalculations::ComputeChi2(
                const AliHLTFloat32_t* x, const AliHLTFloat32_t* y,
                const AliHLTFloat32_t* z, AliHLTUInt32_t n
index f5832e3..9f77b17 100644 (file)
@@ -76,6 +76,11 @@ public:
                        const AliHLTFloat32_t* z, AliHLTUInt32_t n
                );
        
+       static bool FitLineToData(
+                       const AliHLTFloat32_t* x, const AliHLTFloat32_t* z,
+                       AliHLTUInt32_t n
+               );
+       
        static AliHLTFloat32_t Mzx() { return fgMzx; }
        static AliHLTFloat32_t Mzy() { return fgMzy; }
        static AliHLTFloat32_t Czx() { return fgCzx; }
index aecf987..a1114b5 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "AliHLTMUONTriggerReconstructor.h"
 #include "AliHLTMUONTriggerRecordsBlockStruct.h"
+#include "AliHLTMUONTrigRecsDebugBlockStruct.h"
 #include "AliHLTMUONUtils.h"
 #include "AliHLTMUONConstants.h"
 #include "AliHLTMUONCalculations.h"
 #include <cassert>
 
 
+const AliMUONLocalInfoStruct AliHLTMUONTriggerReconstructor::AliDecoderHandler::fgkNullStruct =
+{
+       0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+
 AliHLTMUONTriggerReconstructor::AliHLTMUONTriggerReconstructor() :
        AliHLTLogging(),
        fDecoder()
 {
        /// Default constructor.
+       
+       fDecoder.MaxRegionals(8);
+       fDecoder.MaxLocals(16);
 }
 
 
@@ -142,7 +152,15 @@ AliHLTMUONTriggerReconstructor::AliDecoderHandler::AliDecoderHandler() :
        fUseLocalId(true),
        fUseCrateId(true),
        fCurrentCrateId(0),
-       fCurrentRegional(0)
+       fCurrentRegional(0),
+       fNextLocalIndex(0),
+       fPrevStruct(&fgkNullStruct),
+       fCurrentStruct(&fgkNullStruct),
+       fNextStruct(&fgkNullStruct),
+       fStoreInfo(false),
+       fInfoBufferSize(0),
+       fInfoBufferCount(0),
+       fInfoBuffer(NULL)
 {
        /// Default constructor just resets the lookup table to zero and local
        /// structure marker pointers to NULL.
@@ -161,19 +179,25 @@ AliHLTMUONTriggerReconstructor::AliDecoderHandler::AliDecoderHandler() :
 }
 
 
+AliHLTMUONTriggerReconstructor::AliDecoderHandler::~AliDecoderHandler()
+{
+       // Default destructor deletes allocated array.
+       
+       if (fInfoBuffer != NULL) delete [] fInfoBuffer;
+}
+
+
 bool AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindStripsOnMT1(
-               const AliMUONLocalInfoStruct* localStruct,
                AliHLTInt32_t& xPos, AliHLTInt32_t& yPos
        )
 {
-       /// This method will find the X and Y strip positions on stations MT1
-       /// of the trigger system which were fired for the corresponding
-       /// L0 local trigger decision.
-       /// [in]  \param localStruct  The local trigger structure as found in the DDL payload.
+       /// This method will find the X and Y strip positions on stations MT1 of the
+       /// trigger system which were fired for the current L0 local trigger decision.
        /// [out] \param xPos  The X strip that was fired.
        /// [out] \param yPos  The Y strip that was fired.
        /// \return  true is returned if a strip was fired, otherwise a warning is
        ///      generated and false is returned.
+       /// \note Values for xPos and yPos are in the range [0..15].
 
        // Try to identify the strips on MT1 (chambers 11 or 12) that fired
        // the trigger and set yPos and xPos to the correct values.
@@ -181,142 +205,97 @@ bool AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindStripsOnMT1(
        // by 2. This depends on the switches in the trigger electronics and how
        // they were configured. To avoid having to try to track this info we
        // just use a trial and error method.
-       yPos = GetLocalYPos(localStruct);
-       AliHLTUInt32_t yStrips = GetLocalY1(localStruct);
-       if (((yStrips >> yPos) & 0x1) == 0x1)
-       {
-               // nothing to do, yPos is already correct.
-       }
-       else if (((yStrips >> (yPos + 1)) & 0x1) == 0x1)
-       {
-               yPos = yPos + 1;
-       }
-       else if (((yStrips >> (yPos / 2)) & 0x1) == 0x1)
+       yPos = GetLocalYPos(fCurrentStruct);
+       AliHLTUInt32_t yStrips1 = GetLocalY1(fCurrentStruct);
+       AliHLTUInt32_t yStrips2 = GetLocalY2(fCurrentStruct);
+       if (((yStrips1 >> yPos) & 0x1) != 0x1 and ((yStrips2 >> yPos) & 0x1) != 0x1)
        {
-               yPos = yPos / 2;
-       }
-       else if (((yStrips >> (yPos / 2 + 1)) & 0x1) == 0x1)
-       {
-               yPos = yPos / 2 + 1;
-       }
-       else
-       {
-               // OK, move onto chamber 12.
-               yStrips = GetLocalY2(localStruct);
-               if (((yStrips >> (yPos)) & 0x1) == 0x1)
-               {
-                       // nothing to do, yPos is already correct.
-               }
-               else if (((yStrips >> (yPos + 1)) & 0x1) == 0x1)
-               {
-                       yPos = yPos + 1;
-               }
-               else if (((yStrips >> (yPos / 2)) & 0x1) == 0x1)
+               if (((yStrips1 >> (yPos / 2)) & 0x1) == 0x1 or ((yStrips2 >> (yPos / 2)) & 0x1) == 0x1)
                {
                        yPos = yPos / 2;
                }
-               else if (((yStrips >> (yPos / 2 + 1)) & 0x1) == 0x1)
-               {
-                       yPos = yPos / 2 + 1;
-               }
                else
                {
-                       // At this point give up on the value of yPos and just
-                       // try find the first strip that was fired.
-                       yStrips = GetLocalY1(localStruct);
-                       for (AliHLTInt32_t i = 0; i < 16; i++)
+                       for (AliHLTInt32_t i = 1; i < 16; ++i)
                        {
-                               if (((yStrips >> i) & 0x1) == 0x1)
+                               if (yPos + i < 16 and (((yStrips1 >> (yPos + i)) & 0x1) == 0x1 or
+                                                      ((yStrips2 >> (yPos + i)) & 0x1) == 0x1)
+                                  )
                                {
-                                       yPos = i;
-                                       goto foundYstrip;
+                                       yPos = yPos + i;
+                                       break;
                                }
-                       }
-                       
-                       yStrips = GetLocalY2(localStruct);
-                       for (AliHLTInt32_t i = 0; i < 16; i++)
-                       {
-                               if (((yStrips >> i) & 0x1) == 0x1)
+                               else if (yPos / 2 + i < 16 and (((yStrips1 >> (yPos / 2 + i)) & 0x1) == 0x1 or
+                                                               ((yStrips2 >> (yPos / 2 + i)) & 0x1) == 0x1)
+                                       )
                                {
-                                       yPos = i;
-                                       goto foundYstrip;
+                                       yPos = yPos / 2 + i;
+                                       break;
+                               }
+                               else if (yPos - i >= 0 and (((yStrips1 >> (yPos - i)) & 0x1) == 0x1 or
+                                                           ((yStrips2 >> (yPos - i)) & 0x1) == 0x1)
+                                       )
+                               {
+                                       yPos = yPos - i;
+                                       break;
+                               }
+                               else if (yPos / 2 - i >= 0 and (((yStrips1 >> (yPos / 2 - i)) & 0x1) == 0x1 or
+                                                               ((yStrips2 >> (yPos / 2 - i)) & 0x1) == 0x1)
+                                       )
+                               {
+                                       yPos = yPos / 2 - i;
+                                       break;
                                }
                        }
-                       
-                       // No y strip found in MT1 so this local trigger circuit
-                       // does not pass the 3/4 coincidence requirement,
-                       // so ignore it and continue.
-                       HLTWarning("Could not find fired Y strip for local trigger"
-                               " structure (regional structure = %d, crate ID = %d, ID = %d),"
-                               " which corresponds to triggered strip YPos = %d.",
-                               fCurrentRegional, fCurrentCrateId, GetLocalId(localStruct),
-                               GetLocalYPos(localStruct)
-                       );
-                       return false;
-                       
-               foundYstrip: ;
+                       if (((yStrips1 >> yPos) & 0x1) != 0x1 and ((yStrips2 >> yPos) & 0x1) != 0x1)
+                       {
+                               // No y strip found in MT1 so this local trigger circuit does not
+                               // pass the 3/4 coincidence requirement, so ignore it and continue.
+                               HLTWarning("Could not find fired Y strip for local trigger"
+                                       " structure (regional structure = %d, crate ID = %d, ID = %d),"
+                                       " which corresponds to triggered strip YPos = %d.",
+                                       fCurrentRegional, fCurrentCrateId, GetLocalId(fCurrentStruct),
+                                       GetLocalYPos(fCurrentStruct)
+                               );
+                               return false;
+                       }
                }
        }
        
        // Now find the X strip on MT1 that fired the trigger.
-       xPos = GetLocalXPos(localStruct);
-       AliHLTUInt32_t xStrips = GetLocalX1(localStruct);
-       if (((xStrips >> (xPos / 2)) & 0x1) == 0x1)
+       xPos = GetLocalXPos(fCurrentStruct) / 2;
+       AliHLTUInt32_t xStrips1 = GetLocalX1(fCurrentStruct);
+       AliHLTUInt32_t xStrips2 = GetLocalX2(fCurrentStruct);
+       if (((xStrips1 >> xPos) & 0x1) != 0x1 and ((xStrips2 >> xPos) & 0x1) != 0x1)
        {
-               xPos = xPos / 2;
-       }
-       else if (((xStrips >> (xPos / 2 + 1)) & 0x1) == 0x1)
-       {
-               xPos = xPos / 2 + 1;
-       }
-       else
-       {
-               // OK, move onto chamber 12.
-               xStrips = GetLocalX2(localStruct);
-               if (((xStrips >> (xPos / 2)) & 0x1) == 0x1)
-               {
-                       xPos = xPos / 2;
-               }
-               else if (((xStrips >> (xPos / 2 + 1)) & 0x1) == 0x1)
+               for (AliHLTInt32_t i = 1; i < 16; ++i)
                {
-                       xPos = xPos / 2 + 1;
-               }
-               else
-               {
-                       // At this point give up on the value of xPos and just
-                       // try find the first strip that was fired.
-                       xStrips = GetLocalX1(localStruct);
-                       for (AliHLTInt32_t i = 0; i < 16; i++)
+                       if (xPos + i < 16 and (((xStrips1 >> (xPos + i)) & 0x1) == 0x1 or
+                                              ((xStrips2 >> (xPos + i)) & 0x1) == 0x1)
+                          )
                        {
-                               if (((xStrips >> i) & 0x1) == 0x1)
-                               {
-                                       xPos = i;
-                                       goto foundXstrip;
-                               }
+                               xPos = xPos + i;
+                               break;
                        }
-                       
-                       xStrips = GetLocalX2(localStruct);
-                       for (AliHLTInt32_t i = 0; i < 16; i++)
+                       else if (xPos - i >= 0 and (((xStrips1 >> (xPos - i)) & 0x1) == 0x1 or
+                                                   ((xStrips2 >> (xPos - i)) & 0x1) == 0x1)
+                               )
                        {
-                               if (((xStrips >> i) & 0x1) == 0x1)
-                               {
-                                       xPos = i;
-                                       goto foundXstrip;
-                               }
+                               xPos = xPos - i;
+                               break;
                        }
-                       
-                       // No x strip found in MT1 so this local trigger circuit
-                       // does not pass the 3/4 coincidence requirement,
-                       // so ignore it and continue.
+               }
+               if (((xStrips1 >> xPos) & 0x1) != 0x1 and ((xStrips2 >> xPos) & 0x1) != 0x1)
+               {
+                       // No x strip found in MT1 so this local trigger circuit does not
+                       // pass the 3/4 coincidence requirement, so ignore it and continue.
                        HLTWarning("Could not find fired X strip for local trigger"
                                " structure (regional structure = %d, crate ID = %d, ID = %d),"
                                " which corresponds to triggered strip XPos = %d.",
-                               fCurrentRegional, fCurrentCrateId, GetLocalId(localStruct),
-                               GetLocalXPos(localStruct)
+                               fCurrentRegional, fCurrentCrateId, GetLocalId(fCurrentStruct),
+                               GetLocalXPos(fCurrentStruct)
                        );
                        return false;
-                       
-               foundXstrip: ;
                }
        }
        
@@ -324,227 +303,260 @@ bool AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindStripsOnMT1(
 }
 
 
-void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindXStrips(
-               const AliMUONLocalInfoStruct* localStruct, AliHLTInt32_t startPos,
-               AliHLTInt32_t pos[4]
+void AliHLTMUONTriggerReconstructor::AliDecoderHandler::SelectXPatterns(
+               AliHLTUInt64_t strips[4]
        )
 {
-       /// Finds the X strips that were fired in the local trigger structure.
-       /// [in] \param  localStruct  The local trigger structure as found in the DDL payload.
-       /// [in] \param  startPos  The first X strip location to start looking from.
-       /// [out] \param pos  Array of X strip positions on chambers 11 to 14. pos[0]
-       ///     is for chamber 11, pos[1] for chamber 12 and so on.
-       ///     The elements of the array will contain -1 if no valid strip position
-       ///     was found for that chamber.
+       // Select the correct X strips to use.
        
-       assert( startPos >= 0 );
+       assert( fCurrentStruct != NULL );
        
-       if (((GetLocalX1(localStruct) >> startPos) & 0x1) == 0x1)
-       {
-               pos[0] = startPos;
-       }
-       else
-       {
-               pos[0] = -1;
-       }
+       strips[0] = AliHLTUInt64_t(GetLocalX1(fPrevStruct)) |
+               (AliHLTUInt64_t(GetLocalX1(fCurrentStruct)) << 16) |
+               (AliHLTUInt64_t(GetLocalX1(fNextStruct)) << 32);
        
-       AliHLTUInt32_t xStrips = GetLocalX2(localStruct);
-       if (GetLocalSXDev(localStruct)) // check the direction of the deviation.
-       {
-               // For hits on chamber 12 we have to look for fired strips
-               // within 1 strip of startPos. Where startPos is the X position
-               // as found by FindStripsOnMT1.
-               if (((xStrips >> startPos) & 0x1) == 0x1)
-               {
-                       pos[1] = startPos;
-               }
-               else if (((xStrips >> (startPos + 1)) & 0x1) == 0x1)
-               {
-                       pos[1] = startPos + 1;
-               }
-               else
-               {
-                       pos[1] = -1;
-               }
+       strips[1] = AliHLTUInt64_t(GetLocalX2(fPrevStruct)) |
+               (AliHLTUInt64_t(GetLocalX2(fCurrentStruct)) << 16) |
+               (AliHLTUInt64_t(GetLocalX2(fNextStruct)) << 32);
                
-               // Given the MT1 coordinate and the deviation information we can
-               // identify the X strip on MT2 that corresponds to the L0 trigger.
-               // For fired strips on MT2 we look for strips that are within 2
-               // strips of the position endPos = (posX + deviation) / 2, where
-               // posX = GetLocalXPos(localStruct);
-               // deviation = GetLocalXDev(localStruct)
-               // We use the 2 strip tollerance because there is a truncation of 1
-               // bit when we apply integer divide by 2.
-               // This procedure should thus apply the same constraints and
-               // tollerance as the L0 electronics for the X strip 'mini-roads',
-               // ref. section 3.4.2.2, "Technical Design Report of the Dimuon
-               // Forward Spectrometer".
-               AliHLTInt32_t endPos = (GetLocalXPos(localStruct) + GetLocalXDev(localStruct)) / 2;
+       strips[2] = AliHLTUInt64_t(GetLocalX3(fPrevStruct)) |
+               (AliHLTUInt64_t(GetLocalX3(fCurrentStruct)) << 16) |
+               (AliHLTUInt64_t(GetLocalX3(fNextStruct)) << 32);
                
-               // Note the order of the checks are such that we choose the strip with
-               // giving the smallest deviation.
-               xStrips = GetLocalX3(localStruct);
-               if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos;
-               }
-               else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos - 1;
-               }
-               else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos + 1;
-               }
-               else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos - 2;
-               }
-               else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos + 2;
-               }
-               else
-               {
-                       pos[2] = -1;
-               }
-               
-               xStrips = GetLocalX4(localStruct);
-               if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1)
+       strips[3] = AliHLTUInt64_t(GetLocalX4(fPrevStruct)) |
+               (AliHLTUInt64_t(GetLocalX4(fCurrentStruct)) << 16) |
+               (AliHLTUInt64_t(GetLocalX4(fNextStruct)) << 32);
+}
+
+
+void AliHLTMUONTriggerReconstructor::AliDecoderHandler::SelectYPatterns(
+               AliHLTInt32_t xpos[4], AliHLTUInt32_t strips[4], AliHLTUInt8_t locId[4]
+       )
+{
+       // Select the correct Y strip patterns and local IDs based on the X strip positions found.
+       
+       AliHLTUInt8_t locIdnext = fUseLocalId ? GetLocalId(fNextStruct) : AliHLTUInt8_t(fNextLocalIndex);
+       if (locIdnext >= 16) locIdnext = 0;
+       AliHLTUInt8_t locIdcurr = fUseLocalId ? GetLocalId(fCurrentStruct) : AliHLTUInt8_t(fNextLocalIndex-1);
+       if (locIdcurr >= 16) locIdcurr = 0;
+       AliHLTUInt8_t locIdprev = fUseLocalId ? GetLocalId(fPrevStruct) : AliHLTUInt8_t(fNextLocalIndex-2);
+       if (locIdprev >= 16) locIdprev = 0;
+       
+       UShort_t patterns[4][3] = {
+               {GetLocalY1(fPrevStruct), GetLocalY1(fCurrentStruct), GetLocalY1(fNextStruct)},
+               {GetLocalY2(fPrevStruct), GetLocalY2(fCurrentStruct), GetLocalY2(fNextStruct)},
+               {GetLocalY3(fPrevStruct), GetLocalY3(fCurrentStruct), GetLocalY3(fNextStruct)},
+               {GetLocalY4(fPrevStruct), GetLocalY4(fCurrentStruct), GetLocalY4(fNextStruct)}
+       };
+       
+       for (int i = 0; i < 4; i++)
+       {
+               // Check if the Y strips for the different local structures are the
+               // same physical strip. If they are then performs a bit or between the
+               // patterns. This is necessary because the signal sometimes does not
+               // propagate in time (in particular for cosmic runs). This has to do with
+               // the calibration of the timings in the trigger electronics. The solution
+               // here is to perform the bitwise or to form the correct strip pattern.
+               UShort_t mergedPattern[3] = {patterns[i][0], patterns[i][1], patterns[i][2]};
+               const AliHLTMUONTriggerRecoLutRow& lutnext = fLookupTable.fRow[fCurrentCrateId][locIdnext][i][1][0];
+               const AliHLTMUONTriggerRecoLutRow& lutcurr = fLookupTable.fRow[fCurrentCrateId][locIdnext][i][1][0];
+               const AliHLTMUONTriggerRecoLutRow& lutprev = fLookupTable.fRow[fCurrentCrateId][locIdnext][i][1][0];
+               if (lutprev.fX == lutcurr.fX and lutprev.fY == lutcurr.fY and lutprev.fZ == lutcurr.fZ)
                {
-                       pos[3] = endPos;
+                       mergedPattern[0] |= patterns[i][1];
+                       mergedPattern[1] |= patterns[i][0];
                }
-               else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1)
+               if (lutnext.fX == lutcurr.fX and lutnext.fY == lutcurr.fY and lutnext.fZ == lutcurr.fZ)
                {
-                       pos[3] = endPos - 1;
+                       mergedPattern[1] |= patterns[i][2];
+                       mergedPattern[2] |= patterns[i][1];
                }
-               else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1)
+       
+               if (xpos[i] >= 32)
                {
-                       pos[3] = endPos + 1;
+                       strips[i] = mergedPattern[2];
+                       locId[i] = locIdnext;
                }
-               else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1)
+               else if (xpos[i] >= 16)
                {
-                       pos[3] = endPos - 2;
+                       strips[i] = mergedPattern[1];
+                       locId[i] = locIdcurr;
                }
-               else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1)
+               else  if (xpos[i] >= 0)
                {
-                       pos[3] = endPos + 2;
+                       strips[i] = mergedPattern[0];
+                       locId[i] = locIdnext;
                }
                else
                {
-                       pos[3] = -1;
+                       // If the X strip could not be found then just look on the
+                       // current local board strips.
+                       strips[i] = mergedPattern[1];
+                       locId[i] = locIdcurr;
                }
        }
-       else
+}
+
+
+void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindXStrips(
+               AliHLTInt32_t startPos, AliHLTUInt64_t strips[4], AliHLTInt32_t pos[4]
+       )
+{
+       /// Finds the X strips that were fired in the local trigger structures.
+       /// [in] \param startPos  The first X strip location to start looking from.
+       /// [in] \param strips  The X strip patterns for chambers 11 to 14 to use.
+       /// [out] \param pos  Array of X strip positions on chambers 11 to 14. pos[0]
+       ///     is for chamber 11, pos[1] for chamber 12 and so on.
+       ///     The elements of the array will contain -1 if no valid strip position
+       ///     was found for that chamber.
+       /// \note Values for startPos and pos are in the range [0..47], where 0..15 is
+       ///     for strip positions in the fPrevStruct patterns, 16..31 for fCurrentStruct
+       ///     and 32..47 for fNextStruct.
+       
+       assert( startPos >= 0 );
+       assert( fCurrentStruct != NULL );
+       
+       if (GetLocalSXDev(fCurrentStruct)) // check the direction of the deviation.
        {
-               // The following code is the same as for the
-               // GetLocalSXDev(localStruct) == true case above, but with the
-               // arithmetic changing sign.
-               if (((xStrips >> startPos) & 0x1) == 0x1)
+               for (int i = 0; i < 2; ++i)
                {
-                       pos[1] = startPos;
-               }
-               else if (startPos - 1 >= 0 and ((xStrips >> (startPos - 1)) & 0x1) == 0x1)
-               {
-                       pos[1] = startPos - 1;
-               }
-               else
-               {
-                       pos[1] = -1;
+                       if (((strips[i] >> startPos) & 0x1) == 0x1)
+                       {
+                               pos[i] = startPos;
+                               continue;
+                       }
+                       for (AliHLTInt32_t j = 1; j < 16; ++j)
+                       {
+                               // We first check the straighter tracklet option, i.e higher momentum.
+                               if (startPos - j >= 0 and ((strips[i] >> (startPos - j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = startPos - j;
+                                       break;
+                               }
+                               else if (startPos + j < 48 and ((strips[i] >> (startPos + j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = startPos + j;
+                                       break;
+                               }
+                       }
+                       if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
                }
                
-               AliHLTInt32_t endPos = (GetLocalXPos(localStruct) - GetLocalXDev(localStruct)) / 2;
+               // Given the MT1 coordinate 'startPos' and the deviation information we can
+               // identify the X strip on MT2 that corresponds to the L0 trigger.
+               // We find fired strips on MT2 by looking for strips around the position
+               // endPos = (posX + deviation) / 2, where posX = GetLocalXPos(fCurrentStruct);
+               // deviation = GetLocalXDev(fCurrentStruct)
+               AliHLTInt32_t endPos = (GetLocalXPos(fCurrentStruct) + GetLocalXDev(fCurrentStruct)) / 2;
+               endPos += 16; // fCurrentStruct strips start at bit 16.
                
-               xStrips = GetLocalX3(localStruct);
-               if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos;
-               }
-               else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos + 1;
-               }
-               else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1)
+               for (int i = 2; i < 4; ++i)
                {
-                       pos[2] = endPos - 1;
-               }
-               else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos + 2;
-               }
-               else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1)
-               {
-                       pos[2] = endPos - 2;
+                       if (((strips[i] >> endPos) & 0x1) == 0x1)
+                       {
+                               pos[i] = endPos;
+                               continue;
+                       }
+                       for (AliHLTInt32_t j = 1; j < 16; ++j)
+                       {
+                               if (endPos - j >= 0 and ((strips[i] >> (endPos - j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = endPos - j;
+                                       break;
+                               }
+                               else if (endPos + j < 48 and ((strips[i] >> (endPos + j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = endPos + j;
+                                       break;
+                               }
+                       }
+                       if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
                }
-               else
+       }
+       else
+       {
+               // Similar logic to the positive deviation case above, but with the
+               // arithmetic inversed.
+               for (int i = 0; i < 2; ++i)
                {
-                       pos[2] = -1;
+                       if (((strips[i] >> startPos) & 0x1) == 0x1)
+                       {
+                               pos[i] = startPos;
+                               continue;
+                       }
+                       for (AliHLTInt32_t j = 1; j < 16; ++j)
+                       {
+                               // We first check the straighter tracklet option, i.e higher momentum.
+                               if (startPos + j < 48 and ((strips[i] >> (startPos + j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = startPos + j;
+                                       break;
+                               }
+                               else if (startPos - j >= 0 and ((strips[i] >> (startPos - j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = startPos - j;
+                                       break;
+                               }
+                       }
+                       if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
                }
                
-               xStrips = GetLocalX4(localStruct);
-               if (endPos >= 0 and ((xStrips >> endPos) & 0x1) == 0x1)
-               {
-                       pos[3] = endPos;
-               }
-               else if (endPos + 1 >= 0 and ((xStrips >> (endPos + 1)) & 0x1) == 0x1)
-               {
-                       pos[3] = endPos + 1;
-               }
-               else if (endPos - 1 >= 0 and ((xStrips >> (endPos - 1)) & 0x1) == 0x1)
-               {
-                       pos[3] = endPos - 1;
-               }
-               else if (endPos + 2 >= 0 and ((xStrips >> (endPos + 2)) & 0x1) == 0x1)
-               {
-                       pos[3] = endPos + 2;
-               }
-               else if (endPos - 2 >= 0 and ((xStrips >> (endPos - 2)) & 0x1) == 0x1)
-               {
-                       pos[3] = endPos - 2;
-               }
-               else
+               AliHLTInt32_t endPos = (GetLocalXPos(fCurrentStruct) - GetLocalXDev(fCurrentStruct)) / 2;
+               endPos += 16; // fCurrentStruct strips start at bit 16.
+               
+               for (int i = 2; i < 4; ++i)
                {
-                       pos[3] = -1;
+                       if (((strips[i] >> endPos) & 0x1) == 0x1)
+                       {
+                               pos[i] = endPos;
+                               continue;
+                       }
+                       for (AliHLTInt32_t j = 1; j < 16; ++j)
+                       {
+                               if (endPos + j < 48 and ((strips[i] >> (endPos + j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = endPos + j;
+                                       break;
+                               }
+                               else if (endPos - j >= 0 and ((strips[i] >> (endPos - j)) & 0x1) == 0x1)
+                               {
+                                       pos[i] = endPos - j;
+                                       break;
+                               }
+                       }
+                       if (((strips[i] >> pos[i]) & 0x1) != 0x1) pos[i] = -1;
                }
        }
 }
 
 
 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindYStrips(
-               const AliMUONLocalInfoStruct* localStruct, AliHLTInt32_t startPos,
-               AliHLTInt32_t pos[4]
+               AliHLTInt32_t startPos, AliHLTUInt32_t strips[4], AliHLTInt32_t pos[4]
        )
 {
-       /// Finds the Y strips that were fired in the local trigger structure.
-       /// [in] \param  localStruct  The local trigger structure as found in the DDL payload.
-       /// [in] \param  startPos  The first Y strip location to start looking from.
+       /// Finds the Y strips that were fired in the local trigger structures.
+       /// [in] \param startPos  The first Y strip location to start looking from.
+       /// [in] \param strips  Array of Y strip patterns to look in for chamber 11 to 14.
        /// [out] \param pos  Array of Y strip positions on chambers 11 to 14. pos[0]
        ///     is for chamber 11, pos[1] for chamber 12 and so on.
        ///     The elements of the array will contain -1 if no valid strip position
        ///     was found for that chamber.
+       /// \note Values for startPos and pos are in the range [0..15].
        
        assert( startPos >= 0 );
        
-       // First we scan from the i'th = startPos strip upwards (i.e. i+1, i+2 etc..)
+       // First we scan from the i'th = startPos strip upwards (i.e. i-1, i, i+1, i+2 etc..)
        // to find the first fired strip. Then we similarly scan downwards
-       // (i.e. i-1, i-2 etc..) to find the first fired strip. We actually only need
-       // to check in the range [i-1 .. i+1] due to the constraint that valid tracks
-       // only have a +/- 1 Y strip deviation on consecutive chambers.
+       // (i.e. i+1, i, i-1, i-2 etc..) to find the first fired strip.
        // Ideally we should have all of posUp[i] == posDown[i] == startPos, but this
-       // need not be the case due to multiple scattering.
-       // This procedure should thus apply the same constraints and tollerance
-       // as the L0 electronics for the Y strip 'roads',
-       // ref. section 3.4.2.2, "Technical Design Report of the Dimuon Forward Spectrometer".
-       AliHLTUInt32_t strips[4] = {
-                       GetLocalY1(localStruct), GetLocalY2(localStruct),
-                       GetLocalY3(localStruct), GetLocalY4(localStruct)
-               };
-       AliHLTUInt8_t posUpCount = 0, posDownCount = 0;
+       // need not be the case due to multiple scattering or if dealing with cosmic tracks.
+       AliHLTUInt8_t posUpCount = 0, posDownCount = 0, posNearestCount = 0;
        AliHLTInt32_t posUp[4] = {-1, -1, -1, -1};
        AliHLTInt32_t posDown[4] = {-1, -1, -1, -1};
+       AliHLTInt32_t posNearest[4] = {-1, -1, -1, -1};
        for (AliHLTInt32_t n = 0; n < 4; n++)
        {
-               for (AliHLTInt32_t i = startPos; i <= startPos+1; i++)
+               for (AliHLTInt32_t i = (startPos >= 1 ? startPos-1 : 0); i <= 15; i++)
                {
                        if (((strips[n] >> i) & 0x1) == 0x1)
                        {
@@ -553,7 +565,7 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindYStrips(
                                break;
                        }
                }
-               for (AliHLTInt32_t i = startPos; i >= 0; i--)
+               for (AliHLTInt32_t i = startPos+1; i >= 0; i--)
                {
                        if (((strips[n] >> i) & 0x1) == 0x1)
                        {
@@ -562,27 +574,91 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::FindYStrips(
                                break;
                        }
                }
+               
+               // 20 Nov 2009: Added scanning on either side of startPos to find the
+               // nearest strip to startPos for pathological cases, where there is
+               // a larger angle or scatter in Y strips than +/- 1 strip, eg. cosmics.
+               if (((strips[n] >> startPos) & 0x1) == 0x1)
+               {
+                       posNearest[n] = startPos;
+                       posNearestCount++;
+               }
+               else
+               {
+                       for (AliHLTInt32_t i = 1; i < 16; ++i)
+                       {
+                               if (((strips[n] >> (startPos + i)) & 0x1) == 0x1)
+                               {
+                                       posNearest[n] = startPos + i;
+                                       posNearestCount++;
+                                       break;
+                               }
+                               else if (((strips[n] >> (startPos - i)) & 0x1) == 0x1)
+                               {
+                                       posNearest[n] = startPos - i;
+                                       posNearestCount++;
+                                       break;
+                               }
+                       }
+               }
        }
        
        // Now select either posUp or posDown, whichever has the most found strips.
-       if (posUpCount > posDownCount)
+       if (posUpCount >= posDownCount and posUpCount >= posNearestCount)
        {
                for (AliHLTInt32_t n = 0; n < 4; n++)
                        pos[n] = posUp[n];
        }
-       else
+       else if (posDownCount >= posUpCount and posDownCount >= posNearestCount)
        {
                for (AliHLTInt32_t n = 0; n < 4; n++)
                        pos[n] = posDown[n];
        }
+       else
+       {
+               for (AliHLTInt32_t n = 0; n < 4; n++)
+                       pos[n] = posNearest[n];
+       }
+}
+
+
+const AliHLTMUONTriggerRecoLutRow& AliHLTMUONTriggerReconstructor::AliDecoderHandler::GetLutRowX(
+               AliHLTInt32_t xPos, AliHLTUInt8_t chamber
+       )
+{
+       // Fetches the appropriate LUT row for a given strip X and Y position.
+       
+       assert( chamber <= 3 );
+       assert( fCurrentCrateId < 16 );
+       
+       int locId = 0;
+       int pos = 0;
+       if (xPos >= 32)
+       {
+               locId = fUseLocalId ? GetLocalId(fNextStruct) : fNextLocalIndex;
+               pos = xPos - 32;
+       }
+       else if (xPos >= 16)
+       {
+               locId = fUseLocalId ? GetLocalId(fCurrentStruct) : fNextLocalIndex-1;
+               pos = xPos - 16;
+       }
+       else if (xPos >= 0)
+       {
+               locId = fUseLocalId ? GetLocalId(fPrevStruct) : fNextLocalIndex-2;
+               pos = xPos;
+       }
+       if (locId < 0 or locId >= 16) locId = 0;
+       if (pos < 0 or pos >= 16) pos = 0;
+       
+       return fLookupTable.fRow[fCurrentCrateId][locId][chamber][0][pos];
 }
 
 
 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
-               AliHLTUInt32_t xStrips, AliHLTUInt32_t yStrips,
-               AliHLTInt32_t xPos, AliHLTInt32_t yPos,
-               AliHLTUInt8_t crateId, AliHLTUInt8_t locId, AliHLTUInt8_t chamber,
-               AliHLTMUONRecHitStruct& hit
+               AliHLTUInt64_t xStrips, AliHLTUInt32_t yStrips,
+               AliHLTInt32_t xPos, AliHLTInt32_t yPos, AliHLTUInt8_t yLocId,
+               AliHLTUInt8_t chamber, AliHLTMUONRecHitStruct& hit
        )
 {
        /// Reconstructs the hit coordinates for the given chamber from the
@@ -595,13 +671,15 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
        ///      Valid range [0..3].
        /// [out] \param hit  This will be filled with the reconstructed hit.
 
-       assert( 0 <= xPos and xPos < 16 );
+       assert( 0 <= xPos and xPos < 48 );
        assert( 0 <= yPos and yPos < 16 );
        assert( ((xStrips >> xPos) & 0x1) == 0x1 );
        assert( ((yStrips >> yPos) & 0x1) == 0x1 );
        assert( chamber <= 3 );
-       assert( crateId < 16 );
-       assert( locId < 16 );
+       assert( fCurrentCrateId < 16 );
+       assert( yLocId < 16 );
+       
+       const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(xPos, chamber);
        
        // Decode the Y position of the hit from the strip position information.
        // If two neighbouring strips were fired then we decluster the strips like
@@ -611,19 +689,18 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
                if (((xStrips >> (xPos+1)) & 0x1) == 0x1)
                {
                        // Strips fired on both sides of strip at xPos so just use the middle one.
-                       hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags;
-                       hit.fY = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY;
-                       hit.fZ = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ;
+                       hit.fFlags = lut.fIdFlags;
+                       hit.fY = lut.fY;
+                       hit.fZ = lut.fZ;
                }
                else
                {
                        // Second strip fired below the one at xPos, so decluster.
-                       assert(xPos-1 < 16);
-                       hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags;
-                       hit.fY = (fLookupTable.fRow[crateId][locId][chamber][0][xPos-1].fY
-                               + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY) * 0.5;
-                       hit.fZ = (fLookupTable.fRow[crateId][locId][chamber][0][xPos-1].fZ
-                               + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ) * 0.5;
+                       assert(xPos-1 < 48);
+                       const AliHLTMUONTriggerRecoLutRow& lut2 = GetLutRowX(xPos-1, chamber);
+                       hit.fFlags = lut.fIdFlags;
+                       hit.fY = (lut2.fY + lut.fY) * 0.5;
+                       hit.fZ = (lut2.fZ + lut.fZ) * 0.5;
                }
        }
        else
@@ -631,19 +708,18 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
                if (((xStrips >> (xPos+1)) & 0x1) == 0x1)
                {
                        // Second strip fired above the one at xPos, so decluster.
-                       assert(xPos+1 < 16);
-                       hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags;
-                       hit.fY = (fLookupTable.fRow[crateId][locId][chamber][0][xPos+1].fY
-                               + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY) * 0.5;
-                       hit.fZ = (fLookupTable.fRow[crateId][locId][chamber][0][xPos+1].fZ
-                               + fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ) * 0.5;
+                       assert(xPos+1 < 48);
+                       const AliHLTMUONTriggerRecoLutRow& lut2 = GetLutRowX(xPos+1, chamber);
+                       hit.fFlags = lut.fIdFlags;
+                       hit.fY = (lut2.fY + lut.fY) * 0.5;
+                       hit.fZ = (lut2.fZ + lut.fZ) * 0.5;
                }
                else
                {
                        // Only strip at xPos fired and neither of its two neighbours.
-                       hit.fFlags = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fIdFlags;
-                       hit.fY = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fY;
-                       hit.fZ = fLookupTable.fRow[crateId][locId][chamber][0][xPos].fZ;
+                       hit.fFlags = lut.fIdFlags;
+                       hit.fY = lut.fY;
+                       hit.fZ = lut.fZ;
                }
        }
        
@@ -654,14 +730,14 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
                if (((yStrips >> (yPos+1)) & 0x1) == 0x1)
                {
                        // Strips fired on both sides of strip at yPos so just use the middle one.
-                       hit.fX = fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX;
+                       hit.fX = fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX;
                }
                else
                {
                        // Second strip fired below the one at yPos, so decluster.
                        assert(yPos-1 < 16);
-                       hit.fX = (fLookupTable.fRow[crateId][locId][chamber][1][yPos-1].fX
-                               + fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX) * 0.5;
+                       hit.fX = (fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos-1].fX
+                               + fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX) * 0.5;
                }
        }
        else
@@ -670,49 +746,91 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ReconstructHit(
                {
                        // Second strip fired above the one at yPos, so decluster.
                        assert(yPos+1 < 16);
-                       hit.fX = (fLookupTable.fRow[crateId][locId][chamber][1][yPos+1].fX
-                               + fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX) * 0.5;
+                       hit.fX = (fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos+1].fX
+                               + fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX) * 0.5;
                }
                else
                {
                        // Only strip at yPos fired and neither of its two neighbours.
-                       hit.fX = fLookupTable.fRow[crateId][locId][chamber][1][yPos].fX;
+                       hit.fX = fLookupTable.fRow[fCurrentCrateId][yLocId][chamber][1][yPos].fX;
                }
        }
 }
 
 
+void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnNewRegionalStructV2(
+               UInt_t num,
+               const AliMUONRegionalHeaderStruct* regionalStruct,
+               const AliMUONRegionalScalarsStruct* /*scalars*/,
+               const void* /*data*/
+       )
+{
+       // Reset the local trigger structure pointers, and mark the current regional
+       // structure number and Crate ID.
+       
+       fCurrentRegional = num;
+       fCurrentCrateId = (fUseCrateId ? GetRegionalId(regionalStruct) : num);
+       fPrevStruct = fCurrentStruct = fNextStruct = &fgkNullStruct;
+}
+
+
+void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnEndOfRegionalStructV2(
+               UInt_t /*num*/,
+               const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
+               const AliMUONRegionalScalarsStruct* /*scalars*/,
+               const void* /*data*/
+       )
+{
+       // Process the last local trigger structure.
+       
+       fPrevStruct = fCurrentStruct;
+       fCurrentStruct = fNextStruct;
+       fNextStruct = &fgkNullStruct;
+       
+       // The index numbers for fPrevStruct and fCurrentStruct are calculated from
+       // fNextLocalIndex in ProcessLocalStruct so we need to increment it correctly.
+       ++fNextLocalIndex;
+       
+       ProcessLocalStruct();
+}
+
+
 void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
                UInt_t iloc,
                const AliMUONLocalInfoStruct* localStruct,
                const AliMUONLocalScalarsStruct* /*scalars*/
        )
 {
-       /// Converts a local trigger structure from the L0 into a trigger record.
+       // Update pointers and process the current local trigger structure.
+       
+       assert(iloc < 16);
+       assert(localStruct != NULL);
+       
+       fPrevStruct = fCurrentStruct;
+       fCurrentStruct = fNextStruct;
+       fNextStruct = localStruct;
+       fNextLocalIndex = iloc;
+       ProcessLocalStruct();
+}
+
+
+void AliHLTMUONTriggerReconstructor::AliDecoderHandler::ProcessLocalStruct()
+{
+       /// Converts the fCurrentStruct local trigger structure from the L0 into a trigger record.
        /// The dHLT trigger records is then used as a seed for tracking algorithms.
        /// \note fOutputTrigRecs must be set before calling the decoder to decode
        ///    a new raw data buffer.
-       /// \param localStruct  This is a pointer to the local L0 trigger structure data.
 
-       assert(iloc < 16);
-       assert(localStruct != NULL);
        assert(fOutputTrigRecs != NULL);
        
-       // We must have at least one bit in each of the 4 strip words otherwise
-       // if one of the words is zero it means we only have X or Y coordinate
-       // information for a station or no coordinate on one of the stations at all.
-       if (localStruct->fX2X1 == 0 or localStruct->fX4X3 == 0 or
-           localStruct->fY2Y1 == 0 or localStruct->fY4Y3 == 0
-          )
-       {
-               return;
-       }
+       // If the current local trigger structure does not have a decision then skip it.
+       if (GetLocalDec(fCurrentStruct) == 0) return;
        
        // First try to identify the X and Y strips on MT1 that fired the trigger.
        // Note: X strips are for the Y axis in ALICE coordinate system,
        // i.e. bending plane. and Y strips for the X axis.
        AliHLTInt32_t xPos, yPos;
-       if (not FindStripsOnMT1(localStruct, xPos, yPos)) return;
+       if (not FindStripsOnMT1(xPos, yPos)) return;
        
        // Check that we will not overflow the output buffer.
        if (fOutputTrigRecsCount >= fMaxOutputTrigRecs)
@@ -726,11 +844,18 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
        
        AliHLTMUONTriggerRecordStruct& trigger = fOutputTrigRecs[fOutputTrigRecsCount];
        
-       // Now try find all the X and Y strips on all 4 trigger chambers.
+       // Now try find all the fired X and Y strips on all 4 trigger chambers.
+       
+       AliHLTUInt64_t xStrips[4];
+       SelectXPatterns(xStrips);
        AliHLTInt32_t stripPosX[4];
-       FindXStrips(localStruct, xPos, stripPosX);
+       // Note: the +16 is because FindStripsOnMT1 returns value in the range [0..15]
+       // for fCurrentStruct, but we need the value in the range [0..47].
+       FindXStrips(xPos+16, xStrips, stripPosX);
+       AliHLTUInt32_t yStrips[4]; AliHLTUInt8_t locId[4];
+       SelectYPatterns(stripPosX, yStrips, locId);
        AliHLTInt32_t stripPosY[4];
-       FindYStrips(localStruct, yPos, stripPosY);
+       FindYStrips(yPos, yStrips, stripPosY);
        
        // hitset indicates which hits on chambers 7 to 10 have been found and filled.
        bool hitset[4] = {false, false, false, false};
@@ -738,16 +863,7 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
        // Reconstruct the hits from the found strips. Also, fill the hitset
        // flags and make sure the hits for which no valid strips were found get
        // set to a nil value.
-       AliHLTUInt32_t xStrips[4] = {
-                       GetLocalX1(localStruct), GetLocalX2(localStruct),
-                       GetLocalX3(localStruct), GetLocalX4(localStruct)
-               };
-       AliHLTUInt32_t yStrips[4] = {
-                       GetLocalY1(localStruct), GetLocalY2(localStruct),
-                       GetLocalY3(localStruct), GetLocalY4(localStruct)
-               };
        int hitCount = 0;
-       AliHLTUInt8_t locId = GetLocalId(localStruct);
        for (int i = 0; i < 4; i++)
        {
                if (stripPosX[i] != -1 and stripPosY[i] != -1)
@@ -755,8 +871,7 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
                        ReconstructHit(
                                        xStrips[i], yStrips[i],
                                        stripPosX[i], stripPosY[i],
-                                       fCurrentCrateId, locId, i,
-                                       trigger.fHit[i]
+                                       locId[i], i, trigger.fHit[i]
                                );
                        hitset[i] = true;
                        hitCount++;
@@ -767,9 +882,81 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
                        hitset[i] = false;
                }
        }
+       
+       if (hitCount < 3)
+       {
+               // If we could not find at least 3 hits, but the trigger fired, then
+               // maybe we have a pathalogical case where 3 X strips and 3 Y strips
+               // fired but one chamber has an X, one a Y and only the other 2 have both
+               // X and Y strips fired.
+               // In such a case we need to try fit a line to X and Y independantly
+               // and form the hits from the best line fit.
+               
+               AliHLTFloat32_t x[4], zx[4], y[4], zy[4];
+               AliHLTUInt32_t nx = 0, ny = 0;
+               for (int i = 0; i < 4; i++)
+               {
+                       if (stripPosX[i] != -1)
+                       {
+                               const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(stripPosX[i], i);
+                               y[ny] = lut.fY;
+                               zy[ny] = lut.fZ;
+                               ++ny;
+                       }
+                       if (stripPosY[i] != -1)
+                       {
+                               const AliHLTMUONTriggerRecoLutRow& lut =
+                                       fLookupTable.fRow[fCurrentCrateId][locId[i]][i][1][stripPosY[i]];
+                               x[nx] = lut.fX;
+                               zx[nx] = lut.fZ;
+                               ++nx;
+                       }
+               }
+               
+               AliHLTFloat32_t mx = 0, cx = 0, my = 0, cy = 0;
+               bool xfitted = AliHLTMUONCalculations::FitLineToData(x, zx, nx);
+               mx = AliHLTMUONCalculations::Mzx();
+               cx = AliHLTMUONCalculations::Czx();
+               bool yfitted = AliHLTMUONCalculations::FitLineToData(y, zy, ny);
+               my = AliHLTMUONCalculations::Mzx();
+               cy = AliHLTMUONCalculations::Czx();
+               if (xfitted and yfitted)
+               {
+                       for (int i = 0; i < 4; i++)
+                       {
+                               if (hitset[i]) continue;  // Leave the found hits alone.
+                               if (stripPosX[i] != -1)
+                               {
+                                       // Got X strip but no hit so Y strip is missing.
+                                       // Thus we have a good Y coordinate but poor X.
+                                       const AliHLTMUONTriggerRecoLutRow& lut = GetLutRowX(stripPosX[i], i);
+                                       trigger.fHit[i].fFlags = lut.fIdFlags;
+                                       trigger.fHit[i].fX = mx * lut.fZ + cx;
+                                       trigger.fHit[i].fY = lut.fY;
+                                       trigger.fHit[i].fZ = lut.fZ;
+                                       hitset[i] = true;
+                                       hitCount++;
+                               }
+                               else if (stripPosY[i] != -1)
+                               {
+                                       // Got Y strip but no hit so X strip is missing.
+                                       // Thus we have a good X coordinate but poor Y.
+                                       const AliHLTMUONTriggerRecoLutRow& lut =
+                                               fLookupTable.fRow[fCurrentCrateId][locId[i]][i][1][stripPosY[i]];
+                                       trigger.fHit[i].fFlags = lut.fIdFlags;
+                                       trigger.fHit[i].fX = lut.fX;
+                                       trigger.fHit[i].fY = my * lut.fZ + cy;
+                                       trigger.fHit[i].fZ = lut.fZ;
+                                       hitset[i] = true;
+                                       hitCount++;
+                               }
+                       }
+               }
+       }
 
        // Construct the ID from the running counter fTrigRecId and use the
        // regional counter, local counter and DDL id for the bottom 8 bits.
+       AliHLTUInt8_t iloc = fNextLocalIndex-1;
        trigger.fId = (fTrigRecId << 8) | fDDLBit | ((fCurrentRegional & 0x7) << 4) | (iloc & 0xF);
 
        // Increment the trigger record ID and warp it around at 0x7FFFFF since
@@ -789,6 +976,8 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
        AliHLTMUONCalculations::IdealZ1(chamberZ11);
        AliHLTMUONCalculations::IdealZ2(chamberZ13);
        
+       bool trigAdded = false;
+       
        if (hitCount >= 3 and
            AliHLTMUONCalculations::FitLineToTriggerRecord(trigger, hitset)
           )
@@ -812,6 +1001,7 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
                        );
                
                fOutputTrigRecsCount++;
+               trigAdded = true;
        }
        else if ((hitset[0] or hitset[1] or hitset[2] or hitset[3])
                 and not fSuppressPartialTriggers
@@ -825,6 +1015,62 @@ void AliHLTMUONTriggerReconstructor::AliDecoderHandler::OnLocalStructV2(
                        );
                
                fOutputTrigRecsCount++;
+               trigAdded = true;
+       }
+       
+       if (trigAdded and fStoreInfo)
+       {
+               // Allocate or reallocate buffer.
+               if (fInfoBuffer == NULL)
+               {
+                       try
+                       {
+                               fInfoBuffer = new AliHLTMUONTrigRecInfoStruct[256];
+                       }
+                       catch (...)
+                       {
+                               HLTError("Could not allocate buffer space for debug information.");
+                               return;
+                       }
+                       fInfoBufferSize = 256;
+               }
+               else if (fInfoBufferCount >= fInfoBufferSize)
+               {
+                       AliHLTMUONTrigRecInfoStruct* newbuf = NULL;
+                       try
+                       {
+                               newbuf = new AliHLTMUONTrigRecInfoStruct[fInfoBufferSize*2];
+                       }
+                       catch (...)
+                       {
+                               HLTError("Could not allocate buffer space for debug information.");
+                               return;
+                       }
+                       for (AliHLTUInt32_t i = 0; i < fInfoBufferSize; ++i) newbuf[i] = fInfoBuffer[i];
+                       delete [] fInfoBuffer;
+                       fInfoBuffer = newbuf;
+                       fInfoBufferSize = fInfoBufferSize*2;
+               }
+               
+               fInfoBuffer[fInfoBufferCount].fTrigRecId = trigger.fId;
+               for (int i = 0; i < 4; ++i)
+               {
+                       if (trigger.fHit[i] != AliHLTMUONConstants::NilRecHitStruct())
+                       {
+                               fInfoBuffer[fInfoBufferCount].fDetElemId[i] =
+                                       AliHLTMUONUtils::GetDetElemIdFromFlags(trigger.fHit[i].fFlags);
+                       }
+                       else
+                       {
+                               fInfoBuffer[fInfoBufferCount].fDetElemId[i] = -1;
+                       }
+               }
+               fInfoBuffer[fInfoBufferCount].fZmiddle = AliHLTMUONCalculations::Zf();
+               fInfoBuffer[fInfoBufferCount].fBl = AliHLTMUONCalculations::QBL();
+               fInfoBuffer[fInfoBufferCount].fL0Struct = *fCurrentStruct;
+               fInfoBuffer[fInfoBufferCount].fL0StructPrev = *fPrevStruct;
+               fInfoBuffer[fInfoBufferCount].fL0StructNext = *fNextStruct;
+               ++fInfoBufferCount;
        }
 }
 
index 93ef794..0425a4d 100644 (file)
@@ -32,6 +32,8 @@
 
 extern "C" struct AliHLTMUONRecHitStruct;
 extern "C" struct AliHLTMUONTriggerRecordStruct;
+extern "C" struct AliHLTMUONTrigRecInfoStruct;
+extern "C" struct AliHLTMUONTriggerRecoLutRow;
 
 
 class AliHLTMUONTriggerReconstructor : public AliHLTLogging
@@ -116,6 +118,21 @@ public:
         */
        void UseLocalId(bool value) { fDecoder.GetHandler().UseLocalId(value); }
        
+       /// Return the flag indicating if the debug information is stored during decoding.
+       bool StoreDebugInfo() const { return fDecoder.GetHandler().StoreDebugInfo(); }
+       
+       /// Sets the flag indicating if the debug information should be stored.
+       void StoreDebugInfo(bool value) { fDecoder.GetHandler().StoreDebugInfo(value); }
+       
+       /// Returns the number of elements in the debug information buffer.
+       AliHLTUInt32_t InfoBufferCount() const { return fDecoder.GetHandler().InfoBufferCount(); }
+       
+       /// Returns the debug information buffer.
+       const AliHLTMUONTrigRecInfoStruct* InfoBuffer() const { return fDecoder.GetHandler().InfoBuffer(); }
+       
+       /// Empty the info buffer.
+       void ZeroInfoBuffer() { fDecoder.GetHandler().ZeroInfoBuffer(); }
+       
 private:
 
        class AliDecoderHandler : public AliMUONTriggerDDLDecoderEventHandler, public AliHLTLogging
@@ -125,7 +142,7 @@ private:
                AliDecoderHandler();
                
                /// Default destructor.
-               virtual ~AliDecoderHandler() {}
+               virtual ~AliDecoderHandler();
                
                /// Returns a pointer to the lookup table.
                AliHLTMUONTriggerRecoLookupTable* LookupTableBuffer() { return &fLookupTable; }
@@ -228,14 +245,6 @@ private:
                 */
                void SetDDL(AliHLTInt32_t ddl) { fDDLBit = (ddl == 20 ? 0x00 : 0x80); }
                
-               /**
-                * Generates reconstructed hits from strip information.
-                */
-               bool GenerateHits(
-                               AliHLTMUONRecHitStruct* outputBuffer,
-                               AliHLTUInt32_t& maxEntries
-                       );
-               
                // Methods inherited from AliMUONTriggerDDLDecoderEventHandler:
                
                /// Called for each new buffer. Just remember the start location of the buffer.
@@ -247,21 +256,32 @@ private:
                
                /**
                 * Sets the regional structure sequencial number and decodes the crate ID.
-                * if fUseCrateId is false then we use the sequencial number instead. This
-                * might be necessary for for incorrectly generated or buggy raw data.
+                * Also zero the local structure pointers.
+                * If fUseCrateId is false then we use the sequencial number instead. This
+                * might be necessary for incorrectly generated or buggy raw data.
                 */
                void OnNewRegionalStructV2(
                                UInt_t num,
                                const AliMUONRegionalHeaderStruct* regionalStruct,
                                const AliMUONRegionalScalarsStruct* /*scalars*/,
                                const void* /*data*/
-                       )
-               {
-                       fCurrentRegional = num;
-                       fCurrentCrateId = (fUseCrateId ? GetRegionalId(regionalStruct) : num);
-               }
+                       );
                
-               /// Converts a local trigger structure from the L0 into a trigger record.
+               /**
+                * Updates the local trigger structure pointers and processes the
+                * the last local trigger.
+                */
+               void OnEndOfRegionalStructV2(
+                               UInt_t num,
+                               const AliMUONRegionalHeaderStruct* regionalStruct,
+                               const AliMUONRegionalScalarsStruct* scalars,
+                               const void* data
+                       );
+               
+               /**
+                * Updates the local trigger structure pointers and processes the
+                * current local trigger.
+                */
                void OnLocalStructV2(
                                UInt_t num,
                                const AliMUONLocalInfoStruct* localStruct,
@@ -270,6 +290,21 @@ private:
                
                /// Logs an error message if there was a decoding problem with the DDL payload.
                void OnError(ErrorCode code, const void* location);
+               
+               /// Return the flag indicating if the debug information is stored during decoding.
+               bool StoreDebugInfo() const { return fStoreInfo; }
+               
+               /// Sets the flag indicating if the debug information should be stored.
+               void StoreDebugInfo(bool value) { fStoreInfo = value; }
+               
+               /// Returns the number of elements in the debug information buffer.
+               AliHLTUInt32_t InfoBufferCount() const { return fInfoBufferCount; }
+               
+               /// Returns the debug information buffer.
+               const AliHLTMUONTrigRecInfoStruct* InfoBuffer() const { return fInfoBuffer; }
+               
+               /// Empty the info buffer.
+               void ZeroInfoBuffer() { fInfoBufferCount = 0; }
        
        private:
                // Do not allow copying of this class.
@@ -279,41 +314,59 @@ private:
                AliDecoderHandler& operator = (const AliDecoderHandler& rhs); // assignment operator
                
                /**
-                * Finds the strip bits / positions on MT1 that were fired given
-                * the local trigger structure decision.
+                * Finds the strip bits / positions on MT1 that were fired in
+                * the current local trigger structure decision.
                 */
-               bool FindStripsOnMT1(
-                               const AliMUONLocalInfoStruct* localStruct,
-                               AliHLTInt32_t& xPos, AliHLTInt32_t& yPos
-                       );
+               bool FindStripsOnMT1(AliHLTInt32_t& xPos, AliHLTInt32_t& yPos);
+               
+               /**
+                * Selects the correct X strip patterns to use in FindXStrips.
+                * [out] \param strips  Resulting array of X strip patterns to use
+                *    for chambers 11 to 14.
+                */
+               void SelectXPatterns(AliHLTUInt64_t strips[4]);
+               
+               /**
+                * Selects the correct Y strip patterns to use in FindYStrips and local IDs for
+                * finding the correct row in the lookup table.
+                * [in] \param xpos Array of X strip positions generated by FindXStrips.
+                *    Values are in the range [0..47].
+                * [out] \param strips  Resulting array of Y strip patterns to use.
+                * [out] \param locId  Resulting array of local IDs to use for the lookup table.
+                */
+               void SelectYPatterns(AliHLTInt32_t xpos[4], AliHLTUInt32_t strips[4], AliHLTUInt8_t locId[4]);
                
                /**
                 * Tries to find the fired X strips for chambers 11 to 14.
                 */
-               void FindXStrips(
-                               const AliMUONLocalInfoStruct* localStruct,
-                               AliHLTInt32_t startPos, AliHLTInt32_t pos[4]
-                       );
+               void FindXStrips(AliHLTInt32_t startPos, AliHLTUInt64_t strips[4], AliHLTInt32_t pos[4]);
                
                /**
                 * Tries to find the fired Y strips for chambers 11 to 14.
                 */
-               void FindYStrips(
-                               const AliMUONLocalInfoStruct* localStruct,
-                               AliHLTInt32_t startPos, AliHLTInt32_t pos[4]
-                       );
+               void FindYStrips(AliHLTInt32_t startPos, AliHLTUInt32_t strips[4], AliHLTInt32_t pos[4]);
+               
+               /**
+                * Fetches the appropriate LUT row for a given X strip position.
+                */
+               const AliHLTMUONTriggerRecoLutRow& GetLutRowX(AliHLTInt32_t xPos, AliHLTUInt8_t chamber);
                
                /**
                 * Reconstructs a hit with global position coordinates from strip
                 * information on a given chamber.
                 */
                void ReconstructHit(
-                               AliHLTUInt32_t xStrips, AliHLTUInt32_t yStrips,
-                               AliHLTInt32_t xPos, AliHLTInt32_t yPos,
-                               AliHLTUInt8_t crateId, AliHLTUInt8_t locId,
+                               AliHLTUInt64_t xStrips, AliHLTUInt32_t yStrips,
+                               AliHLTInt32_t xPos, AliHLTInt32_t yPos, AliHLTUInt8_t yLocId,
                                AliHLTUInt8_t chamber, AliHLTMUONRecHitStruct& hit
                        );
                
+               /**
+                * Converts the fCurrentStruct local trigger structure from the L0
+                * into a trigger record.
+                */
+               void ProcessLocalStruct();
+               
                AliHLTMUONTriggerRecoLookupTable fLookupTable;  ///< The lookup table used for mapping between channel addresses and geometrical information.
                const void* fBufferStart; ///< Pointer to the start of the current DDL payload buffer.
                AliHLTUInt32_t fMaxOutputTrigRecs;  ///< Maximum number of reconstructed trigger records that can be stored in fOutputTrigRecs.
@@ -328,6 +381,16 @@ private:
                bool fUseCrateId;  ///< Flag to indicate if the crate ID as found in the regional header structures should be used or not.
                AliHLTInt8_t fCurrentCrateId;  ///< The current trigger crate ID number from the regional header.
                UInt_t fCurrentRegional;  ///< Index number of current regional structure being decoded.
+               UInt_t fNextLocalIndex;  ///< Index number of fNextStruct local structure being decoded.
+               const AliMUONLocalInfoStruct* fPrevStruct;  ///< Previous local trigger structure.
+               const AliMUONLocalInfoStruct* fCurrentStruct;  ///< Current local trigger structure.
+               const AliMUONLocalInfoStruct* fNextStruct;  ///< Next local trigger structure.
+               bool fStoreInfo;  ///< Store debug information in fInfoBuffer.
+               AliHLTUInt32_t fInfoBufferSize;  ///< Number of elements storable in fInfoBuffer.
+               AliHLTUInt32_t fInfoBufferCount;  ///< Number of elements stored in the fInfoBuffer.
+               AliHLTMUONTrigRecInfoStruct* fInfoBuffer;  ///< Buffer for storing the debug information.
+               
+               static const AliMUONLocalInfoStruct fgkNullStruct; ///< Empty structure marker.
        };
 
        /// Not implemented
index ce0840b..4079188 100644 (file)
@@ -106,10 +106,21 @@ void AliHLTMUONTriggerReconstructorComponent::GetInputDataTypes(AliHLTComponentD
 AliHLTComponentDataType AliHLTMUONTriggerReconstructorComponent::GetOutputDataType()
 {
        ///
-       /// Inherited from AliHLTComponent. Returns the output data type.
+       /// Inherited from AliHLTComponent. Returns kAliHLTMultipleDataType.
        ///
        
-       return AliHLTMUONConstants::TriggerRecordsBlockDataType();
+       return kAliHLTMultipleDataType;
+}
+
+
+int AliHLTMUONTriggerReconstructorComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
+{
+       /// Inherited from AliHLTComponent. Returns the output data types.
+       
+       assert( list.empty() );
+       list.push_back( AliHLTMUONConstants::TriggerRecordsBlockDataType() );
+       list.push_back( AliHLTMUONConstants::TrigRecsDebugBlockDataType() );
+       return list.size();
 }
 
 
@@ -169,6 +180,7 @@ int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
        bool suppressPartialTrigs = true;
        bool tryRecover = false;
        bool useLocalId = true;
+       bool makeDebugInfo = false;
        double zmiddle = 0;
        double bfieldintegral = 0;
        
@@ -378,6 +390,12 @@ int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
                        continue;
                }
                
+               if (strcmp( argv[i], "-makedebuginfo" ) == 0)
+               {
+                       makeDebugInfo = true;
+                       continue;
+               }
+               
                HLTError("Unknown option '%s'.", argv[i]);
                return -EINVAL;
                
@@ -491,6 +509,7 @@ int AliHLTMUONTriggerReconstructorComponent::DoInit(int argc, const char** argv)
        fTrigRec->TryRecover(tryRecover);
        fTrigRec->UseCrateId(fUseCrateId);
        fTrigRec->UseLocalId(useLocalId);
+       fTrigRec->StoreDebugInfo(makeDebugInfo);
        
        return 0;
 }
@@ -641,7 +660,7 @@ int AliHLTMUONTriggerReconstructorComponent::DoEvent(
                if (not block.InitCommonHeader())
                {
                        HLTError("There is not enough space in the output buffer for the new data block."
-                                " We require at least %ufTrigRec->GetkDDLHeaderSize() bytes, but have %u bytes left.",
+                                " We require at least %u bytes, but have %u bytes left.",
                                sizeof(AliHLTMUONTriggerRecordsBlockWriter::HeaderType),
                                block.BufferSize()
                        );
@@ -706,12 +725,53 @@ int AliHLTMUONTriggerReconstructorComponent::DoEvent(
                outputBlocks.push_back(bd);
                
                HLTDebug("Created a new output data block at fPtr = %p,"
-                         " with fOffset = %u (0x%.X) and fSize = %u bytes.", 
+                         " with fOffset = %u (0x%.X) and fSize = %u bytes.",
                        bd.fPtr, bd.fOffset, bd.fOffset, bd.fSize
                );
                
                // Increase the total amount of data written so far to our output memory.
                totalSize += block.BytesUsed();
+               
+               if (fTrigRec->StoreDebugInfo())
+               {
+                       // Create a new output data block and initialise the header.
+                       AliHLTMUONTrigRecsDebugBlockWriter infoblock(outputPtr+totalSize, size-totalSize);
+                       if (not infoblock.InitCommonHeader())
+                       {
+                               HLTError("There is not enough space in the output buffer for the new debug"
+                                       " data block. We require at least %u bytes, but have %u bytes left.",
+                                       sizeof(AliHLTMUONTrigRecsDebugBlockWriter::HeaderType),
+                                       infoblock.BufferSize()
+                               );
+                               break;
+                       }
+                       
+                       infoblock.SetNumberOfEntries(fTrigRec->InfoBufferCount());
+                       for (AliHLTUInt32_t i = 0; i < fTrigRec->InfoBufferCount(); ++i)
+                       {
+                               infoblock[i] = fTrigRec->InfoBuffer()[i];
+                       }
+                       fTrigRec->ZeroInfoBuffer();
+                       
+                       // Fill the block data structure for our output block.
+                       AliHLTComponentBlockData bd2;
+                       FillBlockData(bd2);
+                       bd2.fPtr = outputPtr;
+                       // This block's start (offset) is after all other blocks written so far.
+                       bd2.fOffset = totalSize;
+                       bd2.fSize = infoblock.BytesUsed();
+                       bd2.fDataType = AliHLTMUONConstants::TrigRecsDebugBlockDataType();
+                       bd2.fSpecification = blocks[n].fSpecification;
+                       outputBlocks.push_back(bd2);
+                       
+                       HLTDebug("Created a new output data block for debug information at fPtr = %p,"
+                               " with fOffset = %u (0x%.X) and fSize = %u bytes.",
+                               bd2.fPtr, bd2.fOffset, bd2.fOffset, bd2.fSize
+                       );
+                       
+                       // Increase the total amount of data written so far to our output memory.
+                       totalSize += infoblock.BytesUsed();
+               }
        }
        
        // Finally we set the total size of output memory we consumed.
index c43e965..3d4fdb2 100644 (file)
@@ -39,7 +39,8 @@ class AliHLTMUONTriggerReconstructor;
  * Component ID: \b MUONTriggerReconstructor <br>
  * Library: \b libAliHLTMUON.so   <br>
  * Input Data Types: AliHLTMUONConstants::DDLRawDataType() = "DDL_RAW :MUON" <br>
- * Output Data Types: AliHLTMUONConstants::TriggerRecordsBlockDataType() = "TRIGRECS:MUON" <br>
+ * Output Data Types: \li AliHLTMUONConstants::TriggerRecordsBlockDataType() = "TRIGRECS:MUON"
+ *                    \li AliHLTMUONConstants::TrigRecsDebugBlockDataType() = "TRIGRDBG:MUON" <br>
  *
  * <h2>Mandatory arguments:</h2>
  * \li -ddl <i>number</i> <br>
@@ -122,6 +123,8 @@ class AliHLTMUONTriggerReconstructor;
  * \li -dumppath <i>path</i> <br>
  *      Allows one to specify the path in which to dump the received data blocks
  *      if an error occurs. <br>
+ * \li -makedebuginfo <br>
+ *      If specified then the trigger record debug informaiton data blocks are generated. <br>
  *
  * <h2>Standard configuration:</h2>
  * The configuration is taken from the CDB by default. It can be overridden with
@@ -158,6 +161,7 @@ public:
        virtual const char* GetComponentID();
        virtual void GetInputDataTypes(AliHLTComponentDataTypeList& list);
        virtual AliHLTComponentDataType GetOutputDataType();
+       virtual int GetOutputDataTypes(AliHLTComponentDataTypeList& list);
        virtual void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier);
        virtual AliHLTComponent* Spawn();
        
index 1216a5d..ff39b61 100644 (file)
@@ -424,17 +424,18 @@ void RunChain(
                        string name = (k <= 20) ? "MUONHitReconstructor" : "MUONTriggerReconstructor";
                        string parent = Form("pubDDL%d", k);
                        string cmd;
+                       const char* extraInfoFlags = k < 21 ? "-makeclusters -makechannels" : "-makedebuginfo";
                        if (TString(lutDir) == "CDB")
                        {
                                const char* path = cdbManager->GetDefaultStorage()->GetURI().Data();
-                               cmd = Form("-ddl %d -cdbpath %s -run %d %s",
-                                       k, path, cdbManager->GetRun(), recoverFlag
+                               cmd = Form("-ddl %d -cdbpath %s -run %d %s %s",
+                                       k, path, cdbManager->GetRun(), recoverFlag, extraInfoFlags
                                );
                        }
                        else
                        {
-                               cmd = Form("-ddl %d -lut %s/Lut%d.dat %s",
-                                       k, lutDir, k, recoverFlag
+                               cmd = Form("-ddl %d -lut %s/Lut%d.dat %s %s",
+                                       k, lutDir, k, recoverFlag, extraInfoFlags
                                );
                        }
                        if (k >= 21)
index 83ac716..c6c24d5 100644 (file)
@@ -1380,6 +1380,76 @@ int DumpTriggerRecordsBlock(
 }
 
 
+int DumpLocalStruct(
+               const char* buffer, unsigned long bufferSize,
+               const AliMUONLocalInfoStruct* localStruct,
+               bool continueParse,
+               const char* title = ""
+       )
+{
+       // Prints the fields of a L0 local structure as found in the buffer.
+       
+       typedef AliMUONTriggerDDLDecoderEventHandler AliH;
+       
+       cout << "L0 strip patterns" << title << ":" << endl;
+       cout << "Chamber |        X         |         Y        " << endl;
+       cout << "----------------------------------------------" << endl;
+       int result = CheckField(localStruct->fX2X1, buffer, bufferSize, continueParse);
+       if (result != EXIT_SUCCESS) return result;
+       cout << "   11     ";
+       PrintBitPattern(AliH::GetLocalX1(localStruct), 16);
+       result = CheckField(localStruct->fY2Y1, buffer, bufferSize, continueParse);
+       if (result != EXIT_SUCCESS) return result;
+       cout << "   ";
+       PrintBitPattern(AliH::GetLocalY1(localStruct), 16);
+       cout << endl;
+       cout << "   12     ";
+       PrintBitPattern(AliH::GetLocalX2(localStruct), 16);
+       cout << "   ";
+       PrintBitPattern(AliH::GetLocalY2(localStruct), 16);
+       cout << endl;
+       
+       result = CheckField(localStruct->fX4X3, buffer, bufferSize, continueParse);
+       if (result != EXIT_SUCCESS) return result;
+       cout << "   13     ";
+       PrintBitPattern(AliH::GetLocalX3(localStruct), 16);
+       result = CheckField(localStruct->fY4Y3, buffer, bufferSize, continueParse);
+       if (result != EXIT_SUCCESS) return result;
+       cout << "   ";
+       PrintBitPattern(AliH::GetLocalY3(localStruct), 16);
+       cout << endl;
+       cout << "   12     ";
+       PrintBitPattern(AliH::GetLocalX4(localStruct), 16);
+       cout << "   ";
+       PrintBitPattern(AliH::GetLocalY4(localStruct), 16);
+       cout << endl;
+       
+       cout << "L0 trigger bits" << title << ": (word = ";
+       result = CheckField(localStruct->fTriggerBits, buffer, bufferSize, continueParse);
+       if (result != EXIT_SUCCESS) return result;
+       cout << showbase << hex << localStruct->fTriggerBits
+               << noshowbase << dec << ")" << endl;
+       cout << "  ID |  Dec | TrigY | YPos | Sign XDev | XDev |  XPos " << endl;
+       cout << "------------------------------------------------------" << endl;
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalId(localStruct)), 4);
+       cout << "   ";
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalDec(localStruct)), 4);
+       cout << "     ";
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalTrigY(localStruct)), 1);
+       cout << "     ";
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalYPos(localStruct)), 4);
+       cout << "       ";
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalSXDev(localStruct)), 1);
+       cout << "       ";
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalXDev(localStruct)), 4);
+       cout << "   ";
+       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalXPos(localStruct)), 5);
+       cout << endl;
+       
+       return result;
+}
+
+
 int DumpTrigRecInfoStruct(
                const char* buffer, unsigned long bufferSize,
                const AliHLTMUONTrigRecInfoStruct* debuginfo,
@@ -1418,62 +1488,12 @@ int DumpTrigRecInfoStruct(
        if (result != EXIT_SUCCESS) return result;
        cout << setw(31) << right << debuginfo->fBl << setw(0) << endl;
        
-       typedef AliMUONTriggerDDLDecoderEventHandler AliH;
-       
-       cout << "L0 strip patterns:" << endl;
-       cout << "Chamber |        X         |         Y        " << endl;
-       cout << "----------------------------------------------" << endl;
-       result = CheckField(debuginfo->fL0Struct.fX2X1, buffer, bufferSize, continueParse);
-       if (result != EXIT_SUCCESS) return result;
-       cout << "   11     ";
-       PrintBitPattern(AliH::GetLocalX1(&debuginfo->fL0Struct), 16);
-       result = CheckField(debuginfo->fL0Struct.fY2Y1, buffer, bufferSize, continueParse);
-       if (result != EXIT_SUCCESS) return result;
-       cout << "   ";
-       PrintBitPattern(AliH::GetLocalY1(&debuginfo->fL0Struct), 16);
-       cout << endl;
-       cout << "   12     ";
-       PrintBitPattern(AliH::GetLocalX2(&debuginfo->fL0Struct), 16);
-       cout << "   ";
-       PrintBitPattern(AliH::GetLocalY2(&debuginfo->fL0Struct), 16);
-       cout << endl;
-       
-       result = CheckField(debuginfo->fL0Struct.fX4X3, buffer, bufferSize, continueParse);
+       result = DumpLocalStruct(buffer, bufferSize, &debuginfo->fL0Struct, continueParse, " for central local structure");
        if (result != EXIT_SUCCESS) return result;
-       cout << "   13     ";
-       PrintBitPattern(AliH::GetLocalX3(&debuginfo->fL0Struct), 16);
-       result = CheckField(debuginfo->fL0Struct.fY4Y3, buffer, bufferSize, continueParse);
+       result = DumpLocalStruct(buffer, bufferSize, &debuginfo->fL0StructPrev, continueParse, " for previous local structure");
        if (result != EXIT_SUCCESS) return result;
-       cout << "   ";
-       PrintBitPattern(AliH::GetLocalY3(&debuginfo->fL0Struct), 16);
-       cout << endl;
-       cout << "   12     ";
-       PrintBitPattern(AliH::GetLocalX4(&debuginfo->fL0Struct), 16);
-       cout << "   ";
-       PrintBitPattern(AliH::GetLocalY4(&debuginfo->fL0Struct), 16);
-       cout << endl;
-       
-       cout << "L0 trigger bits: (word = ";
-       result = CheckField(debuginfo->fL0Struct.fTriggerBits, buffer, bufferSize, continueParse);
+       result = DumpLocalStruct(buffer, bufferSize, &debuginfo->fL0StructNext, continueParse, " for next local structure");
        if (result != EXIT_SUCCESS) return result;
-       cout << showbase << hex << debuginfo->fL0Struct.fTriggerBits
-               << noshowbase << dec << ")" << endl;
-       cout << "  ID |  Dec | TrigY | YPos | Sign XDev | XDev |  XPos " << endl;
-       cout << "------------------------------------------------------" << endl;
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalId(&debuginfo->fL0Struct)), 4);
-       cout << "   ";
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalDec(&debuginfo->fL0Struct)), 4);
-       cout << "     ";
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalTrigY(&debuginfo->fL0Struct)), 1);
-       cout << "     ";
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalYPos(&debuginfo->fL0Struct)), 4);
-       cout << "       ";
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalSXDev(&debuginfo->fL0Struct)), 1);
-       cout << "       ";
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalXDev(&debuginfo->fL0Struct)), 4);
-       cout << "   ";
-       PrintBitPattern(AliHLTUInt32_t(AliH::GetLocalXPos(&debuginfo->fL0Struct)), 5);
-       cout << endl;
        
        return result;
 }