Alternative implementations of preclusterfinder (currently under test)
authorivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 2 Jul 2007 16:38:39 +0000 (16:38 +0000)
committerivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 2 Jul 2007 16:38:39 +0000 (16:38 +0000)
(Laurent)

MUON/AliMUONPreClusterFinderV2.cxx [new file with mode: 0644]
MUON/AliMUONPreClusterFinderV2.h [new file with mode: 0644]
MUON/AliMUONPreClusterFinderV3.cxx [new file with mode: 0644]
MUON/AliMUONPreClusterFinderV3.h [new file with mode: 0644]

diff --git a/MUON/AliMUONPreClusterFinderV2.cxx b/MUON/AliMUONPreClusterFinderV2.cxx
new file mode 100644 (file)
index 0000000..974683f
--- /dev/null
@@ -0,0 +1,268 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPreClusterFinderV2.h"
+
+#include "AliLog.h"
+#include "AliMUONCluster.h"
+#include "AliMpVSegmentation.h"
+#include "TClonesArray.h"
+#include "TVector2.h"
+#include "AliMUONPad.h"
+#include "AliMUONVDigit.h"
+#include "AliMUONVDigitStore.h"
+
+/// \class AliMUONPreClusterFinderV2
+///
+/// Implementation of AliMUONVClusterFinder
+///
+/// This one ressembles the preclustering stage in the original ClusterFinderAZ
+///
+/// \author Laurent Aphecetche
+
+ClassImp(AliMUONPreClusterFinderV2)
+
+//_____________________________________________________________________________
+AliMUONPreClusterFinderV2::AliMUONPreClusterFinderV2()
+: AliMUONVClusterFinder(),
+  fClusters(0x0),
+  fSegmentations(0x0),
+  fDetElemId(0)
+{
+    /// ctor
+  for ( Int_t i = 0; i < 2; ++i )
+  {
+    fPads[i] = 0x0;
+  } 
+}
+
+//_____________________________________________________________________________
+AliMUONPreClusterFinderV2::~AliMUONPreClusterFinderV2()
+{
+  /// dtor : note we're owner of the pads and the clusters, but not of
+  /// the remaining objects (digits, segmentations)
+  delete fClusters;
+  for ( Int_t i = 0; i < 2; ++i )
+  {
+    delete fPads[i];
+  }  
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPreClusterFinderV2::UsePad(const AliMUONPad& pad)
+{
+  /// Add a pad to the list of pads to be considered
+  if ( pad.DetElemId() != fDetElemId )
+  {
+    AliError(Form("Cannot add pad from DE %d to this cluster finder which is "
+                  "currently dealing with DE %d",pad.DetElemId(),fDetElemId));
+    return kFALSE;
+  }
+  
+  new ((*fPads[pad.Cathode()])[fPads[pad.Cathode()]->GetLast()+1]) AliMUONPad(pad); 
+  // FIXME: should set the ClusterId of that new pad to be -1
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPreClusterFinderV2::Prepare(const AliMpVSegmentation* segmentations[2],
+                                 const AliMUONVDigitStore& digitStore)
+// FIXME : add area on which to look for clusters here.
+{
+  /// Prepare for clustering, by giving access to segmentations and digit lists
+  
+  fSegmentations = segmentations;
+  
+  delete fClusters;
+  fClusters = new TClonesArray("AliMUONCluster");
+  for ( Int_t i = 0; i < 2; ++i )
+  {
+    delete fPads[i];
+    fPads[i] = new TClonesArray("AliMUONPad");
+  }
+  
+  fDetElemId = -1;
+  
+  TIter next(digitStore.CreateIterator());
+  AliMUONVDigit* d;
+  
+  while ( ( d = static_cast<AliMUONVDigit*>(next()) ) )
+  {
+    Int_t ix = d->PadX();
+    Int_t iy = d->PadY();
+    Int_t cathode = d->Cathode();
+    AliMpPad pad = fSegmentations[cathode]->PadByIndices(AliMpIntPair(ix,iy));
+    TClonesArray& padArray = *(fPads[cathode]);
+    if ( fDetElemId == -1 ) 
+    {
+      fDetElemId = d->DetElemId();
+    }
+    else
+    {
+      if ( d->DetElemId() != fDetElemId ) 
+      {
+        AliError("Something is seriously wrong with DE. Aborting clustering");
+        return kFALSE;
+      }
+    }
+    
+    AliMUONPad mpad(fDetElemId,cathode,
+                    ix,iy,pad.Position().X(),pad.Position().Y(),
+                    pad.Dimensions().X(),pad.Dimensions().Y(),
+                    d->Charge());
+    if ( d->IsSaturated() ) mpad.SetSaturated(kTRUE); 
+    new (padArray[padArray.GetLast()+1]) AliMUONPad(mpad);      
+  }
+  if ( fPads[0]->GetLast() < 0 && fPads[1]->GetLast() < 0 )
+  {
+    // no pad at all, nothing to do...
+    return kFALSE;
+  }
+
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinderV2::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
+{
+  /// Add a pad to a cluster
+  
+  cluster.AddPad(*pad);
+  pad->SetClusterId(cluster.GetUniqueID());
+  
+  Int_t cathode = pad->Cathode();
+  TClonesArray& padArray = *fPads[cathode];
+  padArray.Remove(pad);
+  TIter next(&padArray);
+  
+  // Check neighbours
+  TObjArray neighbours;
+  AliMpPad p = fSegmentations[pad->Cathode()]->PadByIndices(AliMpIntPair(pad->Ix(),pad->Iy()),kTRUE);
+  Int_t nn = fSegmentations[pad->Cathode()]->GetNeighbours(p,neighbours);
+  for (Int_t in = 0; in < nn; ++in) 
+  {
+    AliMpPad* p = static_cast<AliMpPad*>(neighbours.At(in));
+    
+    TIter next(&padArray);
+    AliMUONPad* p2;
+    
+    while ( ( p2 = static_cast<AliMUONPad*>(next()) ) )
+    {
+        if ( !p2->IsUsed() && p2->Ix()==p->GetIndices().GetFirst() 
+             && p2->Iy() == p->GetIndices().GetSecond() &&
+             p2->Cathode() == pad->Cathode() )
+        {
+          AddPad(cluster,p2);
+        }
+    }
+  } // for (Int_t in = 0;
+}
+
+namespace
+{
+//_____________________________________________________________________________
+Bool_t
+AreOverlapping(const AliMUONPad& pad, const AliMUONCluster& cluster)
+{
+  /// Whether the pad overlaps with the cluster
+  
+  static Double_t precision = 1E-4; // cm
+  static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
+  for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
+  {
+    AliMUONPad* testPad = cluster.Pad(i);
+    // Note: we use negative precision numbers, meaning
+    // the area of the pads will be *increased* by these small numbers
+    // prior to check the overlap by the AreOverlapping method,
+    // so pads touching only by the corners will be considered as
+    // overlapping.    
+    if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
+    {
+      return kTRUE;
+    }
+  }
+  return kFALSE;
+}
+}
+
+//_____________________________________________________________________________
+AliMUONCluster* 
+AliMUONPreClusterFinderV2::NextCluster()
+{
+  /// Builds the next cluster, and returns it.
+  
+  // Start a new cluster
+  Int_t id = fClusters->GetLast()+1;
+  AliMUONCluster* cluster = new ((*fClusters)[id]) AliMUONCluster;
+  cluster->SetUniqueID(id);
+  
+  AliMUONPad* pad;
+  TIter next(fPads[0]);
+  while (  ( pad = static_cast<AliMUONPad*>(next())) && pad->IsUsed() );
+
+  if (!pad) // protection against no pad in first cathode, which might happen
+  {
+    // try other cathode
+    TIter next(fPads[1]);
+    while (  ( pad = static_cast<AliMUONPad*>(next())) && pad->IsUsed() );
+    if (!pad) 
+    {
+      // we are done.
+      return 0x0;
+    }
+    // Builds (recursively) a cluster on second cathode only
+    AddPad(*cluster,pad);
+  }
+  else
+  {
+    // Builds (recursively) a cluster on first cathode only
+      
+    AddPad(*cluster,pad);
+
+    // On the 2nd cathode, only add pads overlapping with the current cluster
+    TIter next1(fPads[1]);
+    AliMUONPad* testPad;
+  
+    while ( ( testPad = static_cast<AliMUONPad*>(next1())))
+    {
+      if ( !testPad->IsUsed() && AreOverlapping(*testPad,*cluster) )
+      {
+        AddPad(*cluster,testPad);
+      }
+    }
+  }
+  
+  if ( cluster->Multiplicity() <= 1 )
+  {
+    if ( cluster->Multiplicity() == 0 ) 
+    {
+      // no pad is suspicious
+      AliWarning("Got an empty cluster...");
+    }
+    // else only 1 pad (not suspicious, but kind of useless, probably noise)
+    // so we remove it from our list
+    fClusters->Remove(cluster);
+    fClusters->Compress();
+    // then proceed further
+    return NextCluster();
+  }
+  
+  return cluster;
+}
diff --git a/MUON/AliMUONPreClusterFinderV2.h b/MUON/AliMUONPreClusterFinderV2.h
new file mode 100644 (file)
index 0000000..6fb0736
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef ALIMUONPRECLUSTERFINDERV2_H
+#define ALIMUONPRECLUSTERFINDERV2_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup rec
+/// \class AliMUONPreClusterFinderV2
+/// \brief A basic pre-cluster finder
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef AliMUONVCLUSTERFINDER_H
+#  include "AliMUONVClusterFinder.h"
+#endif
+
+class TStopwatch;
+class AliMUONPad;
+
+class AliMUONPreClusterFinderV2 : public AliMUONVClusterFinder
+{
+public:
+  AliMUONPreClusterFinderV2();
+  virtual ~AliMUONPreClusterFinderV2();
+  
+  virtual Bool_t Prepare(const AliMpVSegmentation* segmentations[2],
+                         const AliMUONVDigitStore& digitStore);
+  
+  virtual AliMUONCluster* NextCluster();
+
+  virtual Bool_t UsePad(const AliMUONPad& pad);
+  
+private:
+  /// Not implemented
+  AliMUONPreClusterFinderV2(const AliMUONPreClusterFinderV2& rhs);
+  /// Not implemented
+  AliMUONPreClusterFinderV2& operator=(const AliMUONPreClusterFinderV2& rhs);
+
+  void AddPad(AliMUONCluster& cluster, AliMUONPad* pad);
+  
+private:
+  TClonesArray* fClusters; //!< the clusters we've found (owner)
+  const AliMpVSegmentation** fSegmentations; //!< segmentations (not owner)
+  TClonesArray* fPads[2]; //!< the pads corresponding to the digits (owner)
+  Int_t fDetElemId; //!< which DE we're considering
+  
+  ClassDef(AliMUONPreClusterFinderV2,1) // A basic pre-cluster finder
+};
+
+#endif
diff --git a/MUON/AliMUONPreClusterFinderV3.cxx b/MUON/AliMUONPreClusterFinderV3.cxx
new file mode 100644 (file)
index 0000000..c7a3a56
--- /dev/null
@@ -0,0 +1,334 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPreClusterFinderV3.h"
+
+#include "AliLog.h"
+#include "AliMUONCluster.h"
+#include "AliMpVSegmentation.h"
+#include "TClonesArray.h"
+#include "AliMpArea.h"
+#include "TVector2.h"
+#include "AliMUONPad.h"
+#include "AliMUONVDigit.h"
+#include "AliMUONVDigitStore.h"
+#include <Riostream.h>
+//#include "AliCodeTimer.h"
+
+/// \class AliMUONPreClusterFinderV3
+///
+/// Implementation of AliMUONVClusterFinder
+///
+/// This version uses a 2 steps approach :
+///
+/// we first clusterize each cathode independently to form proto-preclusters, 
+/// and then we try to "merge" proto-preclusters from the two cathodes
+/// when thoses proto-preclusters overlap, thus ending up with preclusters
+/// spanning the two cathodes.
+///
+/// This implementation, on the contrary to PreClusterFinder or PreClusterFinderV2
+/// should not depend on the order of the input digits.
+///
+/// \author Laurent Aphecetche
+
+ClassImp(AliMUONPreClusterFinderV3)
+
+namespace
+{
+  //___________________________________________________________________________
+  Bool_t
+  AreOverlapping(const AliMUONPad& pad, const AliMUONCluster& cluster)
+  {
+    /// Whether the pad overlaps with the cluster
+    
+    static Double_t precision = 1E-4; // cm
+    static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
+      for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
+      {
+        AliMUONPad* testPad = cluster.Pad(i);
+        // Note: we use negative precision numbers, meaning
+        // the area of the pads will be *increased* by these small numbers
+        // prior to check the overlap by the AreOverlapping method,
+        // so pads touching only by the corners will be considered as
+        // overlapping.    
+        if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
+        {
+          return kTRUE;
+        }
+      }
+      return kFALSE;
+  }
+}
+
+//_____________________________________________________________________________
+AliMUONPreClusterFinderV3::AliMUONPreClusterFinderV3()
+: AliMUONVClusterFinder(),
+  fClusters(new TClonesArray("AliMUONCluster",10)),
+  fSegmentations(0x0),
+  fDetElemId(0),
+  fIterator(0x0)
+{
+    /// ctor
+    AliInfo("")
+  for ( Int_t i = 0; i < 2; ++i )
+  {
+    fPads[i] = new TClonesArray("AliMUONPad",100);
+    fPreClusters[i] = new TClonesArray("AliMUONCluster",10);
+  } 
+}
+
+//_____________________________________________________________________________
+AliMUONPreClusterFinderV3::~AliMUONPreClusterFinderV3()
+{
+  /// dtor : note we're owner of the pads and the clusters, but not of
+  /// the remaining objects (digits, segmentations)
+  delete fClusters;
+  for ( Int_t i = 0; i < 2; ++i )
+  {
+    delete fPads[i];
+    delete fPreClusters[i];
+  } 
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPreClusterFinderV3::UsePad(const AliMUONPad& pad)
+{
+  /// Add a pad to the list of pads to be considered
+  if ( pad.DetElemId() != fDetElemId )
+  {
+    AliError(Form("Cannot add pad from DE %d to this cluster finder which is "
+                  "currently dealing with DE %d",pad.DetElemId(),fDetElemId));
+    return kFALSE;
+  }
+  
+  AliMUONPad* p = new ((*fPads[pad.Cathode()])[fPads[pad.Cathode()]->GetLast()+1]) AliMUONPad(pad); 
+  p->SetClusterId(-1);
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPreClusterFinderV3::Prepare(const AliMpVSegmentation* segmentations[2],
+                                 const AliMUONVDigitStore& digitStore)
+{
+  /// Prepare for clustering, by giving access to segmentations and digit lists
+  // FIXME : add area on which to look for clusters here.
+  
+  fSegmentations = segmentations;
+  
+  fClusters->Clear("C");
+  for ( Int_t i = 0; i < 2; ++i )
+  {
+    fPads[i]->Clear("C");
+    fPreClusters[i]->Clear("C");
+  }
+  
+  fDetElemId = -1;
+  
+  TIter next(digitStore.CreateIterator());
+  AliMUONVDigit* d;
+  
+  while ( ( d = static_cast<AliMUONVDigit*>(next()) ) )
+  {
+    Int_t ix = d->PadX();
+    Int_t iy = d->PadY();
+    Int_t cathode = d->Cathode();
+    AliMpPad pad = fSegmentations[cathode]->PadByIndices(AliMpIntPair(ix,iy));
+    TClonesArray& padArray = *(fPads[cathode]);
+    if ( fDetElemId == -1 ) 
+    {
+      fDetElemId = d->DetElemId();
+    }
+    else
+    {
+      if ( d->DetElemId() != fDetElemId ) 
+      {
+        AliError("Something is seriously wrong with DE. Aborting clustering");
+        return kFALSE;
+      }
+    }
+    
+    AliMUONPad mpad(fDetElemId,cathode,
+                    ix,iy,pad.Position().X(),pad.Position().Y(),
+                    pad.Dimensions().X(),pad.Dimensions().Y(),
+                    d->Charge());
+    if ( d->IsSaturated() ) mpad.SetSaturated(kTRUE); 
+    new (padArray[padArray.GetLast()+1]) AliMUONPad(mpad);      
+  }
+  if ( fPads[0]->GetLast() < 0 && fPads[1]->GetLast() < 0 )
+  {
+    // no pad at all, nothing to do...
+    return kFALSE;
+  }
+  
+  MakeCathodePreClusters(0);  
+  MakeCathodePreClusters(1);  
+  MakeClusters();
+  
+  delete fIterator;
+  fIterator = fClusters->MakeIterator();
+  
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinderV3::DumpPreClusters() const
+{
+  /// Dump preclusters 
+  AliMUONCluster *c;
+  TIter next0(fPreClusters[0]);
+  TIter next1(fPreClusters[1]);
+  cout << "Cath0" << endl;
+  while ( ( c = static_cast<AliMUONCluster*>(next0())) ) 
+  {
+    cout << c->AsString().Data() << endl;
+  }
+  cout << "Cath1" << endl;
+  while ( ( c = static_cast<AliMUONCluster*>(next1())) ) 
+  {
+    cout << c->AsString().Data() << endl;
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinderV3::AddPreCluster(AliMUONCluster& cluster, AliMUONCluster* preCluster)
+{
+  /// Add a pad to a cluster
+
+  AliMUONCluster a(*preCluster);
+
+  Int_t cathode = preCluster->Cathode();
+  if ( cathode <=1 && !fPreClusters[cathode]->Remove(preCluster) ) 
+  {
+    AliError(Form("Could not remove %s from preclusters[%d]",
+                  preCluster->AsString().Data(),cathode));
+    StdoutToAliDebug(1,DumpPreClusters());
+    AliFatal("");
+  }
+             
+  cluster.AddCluster(a);
+  
+  // loop on the *other* cathode
+  TIter next(fPreClusters[1-cathode]);
+  AliMUONCluster* testCluster;
+  
+  while ( ( testCluster = static_cast<AliMUONCluster*>(next())))
+  {
+    if ( AliMUONCluster::AreOverlapping(a,*testCluster) )
+    {
+      AddPreCluster(cluster,testCluster);
+    }
+  }
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinderV3::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
+{
+  /// Add a pad to a cluster
+  AliMUONPad* addedPad = cluster.AddPad(*pad);
+  
+  Int_t cathode = pad->Cathode();
+  TClonesArray& padArray = *fPads[cathode];
+  padArray.Remove(pad);
+  TIter next(&padArray);
+  AliMUONPad* testPad;
+  
+  while ( ( testPad = static_cast<AliMUONPad*>(next())))
+  {
+    if ( AliMUONPad::AreNeighbours(*testPad,*addedPad) )
+    {
+      AddPad(cluster,testPad);
+    }
+  }
+}
+
+//_____________________________________________________________________________
+AliMUONCluster* 
+AliMUONPreClusterFinderV3::NextCluster()
+{
+  /// Returns the next cluster
+  
+  return static_cast<AliMUONCluster*>(fIterator->Next());
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinderV3::MakeClusters()
+{
+  /// Associate (proto)preclusters to form (pre)clusters
+  
+//  AliCodeTimerAuto("")
+  
+  for ( Int_t cathode = 0; cathode < 2; ++cathode ) 
+  {
+    TClonesArray& preclusters = *(fPreClusters[cathode]);
+    
+    TIter next(&preclusters);
+    AliMUONCluster* preCluster(0x0);
+    
+    while ( ( preCluster = static_cast<AliMUONCluster*>(next()) ) )
+    {
+      Int_t id(fClusters->GetLast()+1);
+      AliMUONCluster* cluster = new((*fClusters)[id]) AliMUONCluster;
+      cluster->SetUniqueID(id);      
+      AddPreCluster(*cluster,preCluster);
+    }
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinderV3::MakeCathodePreClusters(Int_t cathode)
+{
+  /// Build (proto)preclusters from digits on a given cathode
+  
+//  AliCodeTimerAuto(Form("Cathode %d",cathode))
+  
+  while ( fPads[cathode]->GetLast() > 0  )
+  {  
+    TIter next(fPads[cathode]);
+    AliMUONPad* pad = static_cast<AliMUONPad*>(next());
+  
+    if (!pad) AliFatal("");
+
+    Int_t id = fPreClusters[cathode]->GetLast()+1;
+    AliMUONCluster* cluster = new ((*fPreClusters[cathode])[id]) AliMUONCluster;
+    cluster->SetUniqueID(id);
+    
+    // Builds (recursively) a cluster on first cathode only
+    AddPad(*cluster,pad);
+    
+    if ( cluster->Multiplicity() <= 1 )
+    {
+      if ( cluster->Multiplicity() == 0 ) 
+      {
+        // no pad is suspicious
+        AliWarning("Got an empty cluster...");
+      }
+      // else only 1 pad (not suspicious, but kind of useless, probably noise)
+      // so we remove it from our list
+      fPreClusters[cathode]->Remove(cluster);
+      // then proceed further
+    }
+  }
+  
+}
diff --git a/MUON/AliMUONPreClusterFinderV3.h b/MUON/AliMUONPreClusterFinderV3.h
new file mode 100644 (file)
index 0000000..7940ba0
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef ALIMUONPRECLUSTERFINDERV3_H
+#define ALIMUONPRECLUSTERFINDERV3_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup rec
+/// \class AliMUONPreClusterFinderV3
+/// \brief A basic pre-cluster finder
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef AliMUONVCLUSTERFINDER_H
+#  include "AliMUONVClusterFinder.h"
+#endif
+
+class TIterator;
+class AliMUONPad;
+
+class AliMUONPreClusterFinderV3 : public AliMUONVClusterFinder
+{
+public:
+  AliMUONPreClusterFinderV3();
+  virtual ~AliMUONPreClusterFinderV3();
+  
+  virtual Bool_t Prepare(const AliMpVSegmentation* segmentations[2],
+                         const AliMUONVDigitStore& digitStore);
+  
+  virtual AliMUONCluster* NextCluster();
+
+  virtual Bool_t UsePad(const AliMUONPad& pad);
+  
+private:
+  /// Not implemented
+  AliMUONPreClusterFinderV3(const AliMUONPreClusterFinderV3& rhs);
+  /// Not implemented
+  AliMUONPreClusterFinderV3& operator=(const AliMUONPreClusterFinderV3& rhs);
+
+  void AddPad(AliMUONCluster& cluster, AliMUONPad* pad);
+  void AddPreCluster(AliMUONCluster& cluster, AliMUONCluster* preCluster);
+  void MakeCathodePreClusters(Int_t cathode);
+  void MakeClusters();
+  
+  void DumpPreClusters() const;
+  
+private:
+  TClonesArray* fClusters; //!< the clusters we've found (owner)
+  const AliMpVSegmentation** fSegmentations; //!< segmentations (not owner)
+  TClonesArray* fPads[2]; //!< the pads corresponding to the digits (owner)
+  TClonesArray* fPreClusters[2]; //!< the preclusters per cathode (owner)
+  Int_t fDetElemId; //!< which DE we're considering
+  TIterator* fIterator; //!< iterator on fClusters
+  
+  ClassDef(AliMUONPreClusterFinderV3,1) // A basic pre-cluster finder
+};
+
+#endif