#include "AliMUONPreClusterFinder.h"
-#include "AliLog.h"
+#include "AliCodeTimer.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 "AliCodeTimer.h"
+#include "AliMpArea.h"
+#include "AliMpConstants.h"
+#include "AliMpVSegmentation.h"
+
+#include "AliLog.h"
+
+#include <Riostream.h>
+#include <TObjArray.h>
+#include <TVector2.h>
+
+//-----------------------------------------------------------------------------
/// \class AliMUONPreClusterFinder
///
/// Implementation of AliMUONVClusterFinder
/// This class simply find adjacent pads to form clusters
///
/// \author Laurent Aphecetche
+//-----------------------------------------------------------------------------
ClassImp(AliMUONPreClusterFinder)
//_____________________________________________________________________________
AliMUONPreClusterFinder::AliMUONPreClusterFinder()
: AliMUONVClusterFinder(),
- fClusters(0x0),
- fSegmentations(0x0),
- fDetElemId(0)
+ fClusters("AliMUONCluster"),
+ fPads(0x0),
+ fDetElemId(0),
+ fArea(),
+ fShouldAbort(kFALSE)
{
- /// ctor
- for ( Int_t i = 0; i < 2; ++i )
- {
- fPads[i] = 0x0;
- }
+ /// ctor
}
//_____________________________________________________________________________
AliMUONPreClusterFinder::~AliMUONPreClusterFinder()
{
- /// 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];
- }
+ /// dtor : note we're owner of the clusters, but not of the pads
}
//_____________________________________________________________________________
return kFALSE;
}
- new ((*fPads[pad.Cathode()])[fPads[pad.Cathode()]->GetLast()+1]) AliMUONPad(pad);
+ fPads[pad.Cathode()]->Add(new AliMUONPad(pad));
// FIXME: should set the ClusterId of that new pad to be -1
return kTRUE;
}
//_____________________________________________________________________________
Bool_t
-AliMUONPreClusterFinder::Prepare(const AliMpVSegmentation* segmentations[2],
- const AliMUONVDigitStore& digitStore)
-// FIXME : add area on which to look for clusters here.
+AliMUONPreClusterFinder::Prepare(Int_t detElemId,
+ TObjArray* pads[2],
+ const AliMpArea& area)
{
/// Prepare for clustering, by giving access to segmentations and digit lists
+
+ fClusters.Delete();
- 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;
+ fPads = pads;
+ fDetElemId = detElemId;
+ fArea = area;
- 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;
- }
+ fShouldAbort = kFALSE;
return kTRUE;
}
AliMUONPreClusterFinder::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
{
/// Add a pad to a cluster
- cluster.AddPad(*pad);
+
+ if ( cluster.IsMonoCathode() && cluster.Multiplicity() > 199 )
+ {
+ /// FIXME : we should at that point really find a better way to remove "bad" preclusters,
+ /// like e.g. computing the charge dispersion (the lower, the most probably we have noise cluster)
+ /// and/or mean charge per pad (if too close to LowestPadCharge, again that's a noise cluster...
+ /// *BUT* this needs carefull testing !
+ fShouldAbort = kTRUE;
+ return;
+ }
+
+ AliMUONPad* addedPad = cluster.AddPad(*pad);
Int_t cathode = pad->Cathode();
- TClonesArray& padArray = *fPads[cathode];
+ TObjArray& padArray = *fPads[cathode];
// WARNING: this Remove method uses the AliMUONPad::IsEqual if that method is
// present (otherwise just compares pointers) : so that one must be correct
// if implemented !
- padArray.Remove(pad);
- // TObject* o = padArray.Remove(pad);
+ TObject* o = padArray.Remove(pad);
// if (!o)
// {
// AliFatal("Oups. Could not remove pad from pads to consider. Aborting as anyway "
// " we'll get an infinite loop. Please check the AliMUONPad::IsEqual method"
// " as the first suspect for failed remove");
// }
+ delete o;
+
TIter next(&padArray);
AliMUONPad* testPad;
while ( ( testPad = static_cast<AliMUONPad*>(next())))
{
- if ( AliMUONPad::AreNeighbours(*testPad,*pad) )
+ if ( AliMUONPad::AreNeighbours(*testPad,*addedPad) )
{
AddPad(cluster,testPad);
}
return kFALSE;
}
+//_____________________________________________________________________________
+AliMUONPad*
+AliMUONPreClusterFinder::GetNextPad(Int_t cathode) const
+{
+/// Return the next unused pad of given cathode, which is within fArea
+
+ TIter next(fPads[cathode]);
+
+ if ( !fArea.IsValid() )
+ {
+ return static_cast<AliMUONPad*>(next());
+ }
+ else
+ {
+ AliMUONPad* pad;
+ while ( ( pad = static_cast<AliMUONPad*>(next())) )
+ {
+ AliMpArea padArea(pad->X(), pad->Y(), pad->DX(), pad->DY());
+
+ if (fArea.Overlap(padArea)) return pad;
+
+ }
+ return 0x0;
+ }
+}
+
+//_____________________________________________________________________________
+AliMUONCluster*
+AliMUONPreClusterFinder::NewCluster()
+{
+ /// Create a new (empty) cluster
+ Int_t id = fClusters.GetLast()+1;
+ AliMUONCluster* cluster = new (fClusters[id]) AliMUONCluster;
+ cluster->SetUniqueID(id);
+ return cluster;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreClusterFinder::RemoveCluster(AliMUONCluster* cluster)
+{
+ /// Remove a cluster
+ /// Note that we are *not* releasing the pads, so they won't be used further on
+ fClusters.Remove(cluster);
+ fClusters.Compress();
+}
+
//_____________________________________________________________________________
AliMUONCluster*
AliMUONPreClusterFinder::NextCluster()
{
/// Builds the next cluster, and returns it.
-// AliCodeTimerAuto("")
-
// Start a new cluster
- Int_t id = fClusters->GetLast()+1;
- AliMUONCluster* cluster = new ((*fClusters)[id]) AliMUONCluster;
- cluster->SetUniqueID(id);
- TIter next(fPads[0]);
- AliMUONPad* pad = static_cast<AliMUONPad*>(next());
+ AliMUONPad* pad = GetNextPad(0);
+
+ AliMUONCluster* cluster(0x0);
if (!pad) // protection against no pad in first cathode, which might happen
{
// try other cathode
- TIter next(fPads[1]);
- pad = static_cast<AliMUONPad*>(next());
+ pad = GetNextPad(1);
if (!pad)
{
- // we are done.
return 0x0;
}
- // Builds (recursively) a cluster on second cathode only
- AddPad(*cluster,pad);
+ else
+ {
+ cluster = NewCluster();
+ // Builds (recursively) a cluster on second cathode only
+ AddPad(*cluster,pad);
+ }
}
else
{
// Builds (recursively) a cluster on first cathode only
+
+ cluster = NewCluster();
AddPad(*cluster,pad);
- // On the 2nd cathode, only add pads overlapping with the current cluster
- TClonesArray& padArray = *fPads[1];
- TIter next(&padArray);
- AliMUONPad* testPad;
-
- while ( ( testPad = static_cast<AliMUONPad*>(next())))
+ if ( !ShouldAbort() )
{
- if ( AreOverlapping(*testPad,*cluster) )
+ // On the 2nd cathode, only add pads overlapping with the current cluster
+ TObjArray& padArray = *fPads[1];
+ TIter next(&padArray);
+ AliMUONPad* testPad;
+
+ while ( ( testPad = static_cast<AliMUONPad*>(next())) && !ShouldAbort() )
{
- AddPad(*cluster,testPad);
+ if (AreOverlapping(*testPad,*cluster) )
+ {
+ AddPad(*cluster,testPad);
+ }
}
}
}
+ if ( ShouldAbort() )
+ {
+ AliCodeTimerAuto(Form("Skipping a precluster in DE %d because it got too many pads",fDetElemId),0);
+ RemoveCluster(cluster);
+ return NextCluster();
+ }
+
if ( cluster->Multiplicity() <= 1 )
{
if ( cluster->Multiplicity() == 0 )
}
// else only 1 pad (not suspicious, but kind of useless, probably noise)
// so we remove it from our list
- fClusters->Remove(cluster);
- fClusters->Compress();
+ RemoveCluster(cluster);
// then proceed further
return NextCluster();
}