#include <TVirtualX.h>
#include "AliMUONCluster.h"
+#include "AliMUONPad.h"
+
+#include "AliMpEncodePair.h"
#include "AliLog.h"
-#include "AliMUONPad.h"
+//-----------------------------------------------------------------------------
/// \class AliMUONCluster
///
/// A group of adjacent pads
///
/// \author Laurent Aphecetche
///
+//-----------------------------------------------------------------------------
+using std::cout;
+using std::endl;
/// \cond CLASSIMP
ClassImp(AliMUONCluster)
/// \endcond
//_____________________________________________________________________________
AliMUONCluster::AliMUONCluster()
: TObject(),
-fPads(0x0),
+fPads(),
fHasPosition(kFALSE),
fPosition(1E9,1E9),
fPositionError(1E9,1E9),
fHasCharge(kFALSE),
-fChi2(0),
-fIsSorted(kFALSE)
+fChi2(0)
{
/// ctor
fMultiplicity[0]=fMultiplicity[1]=0;
fRawCharge[0]=fRawCharge[1]=0;
fCharge[0]=fCharge[1]=0;
fIsSaturated[0]=fIsSaturated[1]=kFALSE;
+ fPads.SetOwner(kTRUE);
}
//_____________________________________________________________________________
AliMUONCluster::AliMUONCluster(const AliMUONCluster& src)
: TObject(src),
-fPads(0x0),
+fPads(),
fHasPosition(kFALSE),
fPosition(1E9,1E9),
fPositionError(1E9,1E9),
fHasCharge(kFALSE),
-fChi2(0),
-fIsSorted(kFALSE)
+fChi2(0)
{
/// copy ctor
+ fPads.SetOwner(kTRUE);
src.Copy(*this);
}
AliMUONCluster::operator=(const AliMUONCluster& src)
{
/// assignement operator
- AliMUONCluster c(src);
- c.Copy(*this);
+ if ( this != &src )
+ {
+ src.Copy(*this);
+ }
return *this;
}
AliMUONCluster::~AliMUONCluster()
{
/// dtor : note that we're owner of our pads
- delete fPads;
+// fPads.Delete();
}
//_____________________________________________________________________________
void
-AliMUONCluster::AddPad(const AliMUONPad& pad)
+AliMUONCluster::Clear(Option_t*)
{
- /// Add a pad to our pad array, and update some internal information
- /// accordingly.
- /// If pad array was sorted prior to this call, we re-sort it after
- /// actual addition.
+ /// Clear our pad array
+ fPads.Clear();
+// fPads.Delete();
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONCluster::Contains(const AliMUONPad& pad) const
+{
+ /// Whether this cluster contains the pad
+ if (fPads.IsEmpty()) return kFALSE;
- if (!fPads)
+ for ( Int_t i = 0; i < Multiplicity(); ++i )
+ {
+ AliMUONPad* p = Pad(i);
+ if ( pad.Compare(p) == 0 ) return kTRUE;
+ }
+ return kFALSE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONCluster::AddCluster(const AliMUONCluster& cluster)
+{
+ /// Add all the pads for cluster to this one
+ for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
{
- fPads = new TObjArray(10);
- fPads->SetOwner(kTRUE);
+ AliMUONPad* p = cluster.Pad(i);
+ if ( Contains(*p) )
+ {
+ AliError("I already got this pad : ");
+ StdoutToAliError(p->Print(););
+ AliFatal("");
+ }
+ AddPad(*p);
}
+
+}
+
+//_____________________________________________________________________________
+AliMUONPad*
+AliMUONCluster::AddPad(const AliMUONPad& pad)
+{
+ /// Add a pad to our pad array, and update some internal information
+ /// accordingly.
+
AliMUONPad* p = new AliMUONPad(pad);
- fPads->AddLast(p);
+ fPads.AddLast(p);
p->SetClusterId(GetUniqueID());
Int_t cathode = p->Cathode();
++(fMultiplicity[cathode]);
{
fIsSaturated[p->Cathode()]=kTRUE;
}
- if ( fIsSorted ) Sort();
+ return p;
+}
+
+//___________________________________________________________________________
+TString
+AliMUONCluster::AsString() const
+{
+ /// Return a string containing a compact form of the pad list
+ TString s(Form("NPADS(%d,%d)",Multiplicity(0),Multiplicity(1)));
+
+ for (Int_t i = 0; i < Multiplicity(); ++i )
+ {
+ AliMUONPad* p = Pad(i);
+ s += Form(" (%d,%d,%d) ",p->Cathode(),p->Ix(),p->Iy());
+ }
+ return s;
+}
+
+
+//___________________________________________________________________________
+Bool_t
+AliMUONCluster::AreOverlapping(const AliMUONCluster& c1, const AliMUONCluster& c2)
+{
+ /// Whether the two clusters overlap
+
+ static Double_t precision = 1E-4; // cm
+ static TVector2 precisionAdjustment(precision,precision);
+
+ for ( Int_t i1 = 0; i1 < c1.Multiplicity(); ++i1 )
+ {
+ AliMUONPad* p1 = c1.Pad(i1);
+
+ for ( Int_t i2 = 0; i2 < c2.Multiplicity(); ++i2 )
+ {
+ AliMUONPad* p2 = c2.Pad(i2);
+ // 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(*p1,*p2,precisionAdjustment) )
+ {
+ return kTRUE;
+ }
+ }
+ }
+ return kFALSE;
}
//_____________________________________________________________________________
}
// then construct the area from those limits
- return AliMpArea((lowerLeft+upperRight)/2,
- (upperRight-lowerLeft)/2);
+ return AliMpArea((lowerLeft+upperRight).X()/2,(lowerLeft+upperRight).Y()/2,
+ (upperRight-lowerLeft).X()/2, (upperRight-lowerLeft).Y()/2);
+}
+
+//_____________________________________________________________________________
+AliMpArea
+AliMUONCluster::Area(Int_t cathode) const
+{
+ /// Return the geometrical area covered by this cluster's pads on
+ /// a given cathode
+
+ // Start by finding the (x,y) limits of this cluster
+ TVector2 lowerLeft(1E9,1E9);
+ TVector2 upperRight(-1E9,-1E9);
+
+ for ( Int_t i = 0; i < Multiplicity(); ++i )
+ {
+ AliMUONPad* pad = Pad(i);
+ if ( pad->Cathode() == cathode )
+ {
+ TVector2 ll = pad->Position() - pad->Dimensions();
+ TVector2 ur = pad->Position() + pad->Dimensions();
+ lowerLeft.Set( TMath::Min(ll.X(),lowerLeft.X()),
+ TMath::Min(ll.Y(),lowerLeft.Y()) );
+ upperRight.Set( TMath::Max(ur.X(),upperRight.X()),
+ TMath::Max(ur.Y(),upperRight.Y()) );
+ }
+ }
+
+ // then construct the area from those limits
+ return AliMpArea((lowerLeft+upperRight).X()/2,(lowerLeft+upperRight).Y()/2,
+ (upperRight-lowerLeft).X()/2, (upperRight-lowerLeft).Y()/2);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONCluster::IsMonoCathode() const
+{
+ /// Whether we have signals only in one of the two cathodes
+ return (Cathode()<2);
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONCluster::Cathode() const
+{
+ /// Return the cathode "number" of this cluster :
+ /// 0 if all its pads are on cathode 0
+ /// 1 if all its pads are on cathode 1
+ /// 2 if some pads on cath 0 and some on cath 1
+
+ Int_t cathode(-1);
+ if (Multiplicity(0)>0 && Multiplicity(1)>0)
+ {
+ cathode=2;
+ }
+ else if (Multiplicity(0)>0)
+ {
+ cathode=0;
+ }
+ else if (Multiplicity(1)>0)
+ {
+ cathode=1;
+ }
+
+ return cathode;
}
//_____________________________________________________________________________
void
AliMUONCluster::Copy(TObject& obj) const
{
- //
- // Copy this cluster to (cluster&)obj
- //
+ ///
+ /// Copy this cluster to (cluster&)obj
+ ///
TObject::Copy(obj);
AliMUONCluster& dest = static_cast<AliMUONCluster&>(obj);
- dest.fPads = static_cast<TObjArray*>(fPads->Clone());
+
+// dest.fPads.Delete();
+ dest.fPads.Clear();
+
+ for ( Int_t i = 0; i <= fPads.GetLast(); ++i )
+ {
+ AliMUONPad* p = static_cast<AliMUONPad*>(fPads.UncheckedAt(i));
+ dest.fPads.AddLast(new AliMUONPad(*p));
+ }
dest.fHasPosition = fHasPosition;
dest.fPosition = fPosition;
dest.fPositionError = fPositionError;
dest.fHasCharge = fHasCharge;
- dest.fIsSorted = fIsSorted;
dest.fChi2 = fChi2;
for ( Int_t i = 0; i < 2; ++i )
{
AliMUONCluster::Charge() const
{
/// Return the average charge over both cathodes
- return (Charge(0)+Charge(1))/2.0;
+
+ if ( Multiplicity(0) && Multiplicity(1) )
+ {
+ return (Charge(0)+Charge(1))/2.0;
+ }
+ else if ( Multiplicity(0) )
+ {
+ return Charge(0);
+ }
+ else if ( Multiplicity(1) )
+ {
+ return Charge(1);
+ }
+ AliError("Should not be here ?!");
+ return -1.0;
}
//_____________________________________________________________________________
return 0;
}
+//_____________________________________________________________________________
+TVector2
+AliMUONCluster::MaxPadDimensions(Int_t statusMask, Bool_t matchMask) const
+{
+ /// Returns the maximum pad dimensions (half sizes), only considering
+ /// pads matching (or not, depending matchMask) a given mask
+
+ TVector2 cath0(MaxPadDimensions(0,statusMask,matchMask));
+ TVector2 cath1(MaxPadDimensions(1,statusMask,matchMask));
+
+ return TVector2( TMath::Max(cath0.X(),cath1.X()),
+ TMath::Max(cath0.Y(),cath1.Y()) );
+}
+
+//_____________________________________________________________________________
+TVector2
+AliMUONCluster::MaxPadDimensions(Int_t cathode,
+ Int_t statusMask, Bool_t matchMask) const
+{
+ /// Returns the maximum pad dimensions (half sizes), only considering
+ /// pads matching (or not, depending matchMask) a given mask, within a
+ /// given cathode
+
+ Double_t xmax(0);
+ Double_t ymax(0);
+
+ for ( Int_t i = 0; i < Multiplicity(); ++i )
+ {
+ AliMUONPad* pad = Pad(i);
+ if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
+ {
+ xmax = TMath::Max(xmax,pad->DX());
+ ymax = TMath::Max(ymax,pad->DY());
+ }
+ }
+ return TVector2(xmax,ymax);
+}
+
//_____________________________________________________________________________
TVector2
AliMUONCluster::MinPadDimensions(Int_t statusMask, Bool_t matchMask) const
}
//_____________________________________________________________________________
-AliMpIntPair
+Long_t
AliMUONCluster::NofPads(Int_t statusMask, Bool_t matchMask) const
{
/// Number of pads satisfying (or not, depending matchMask) a
- /// given mask
+ /// given mask
Int_t nx, ny;
TVector2 dim0(MinPadDimensions(0,statusMask,matchMask));
TVector2 dim1(MinPadDimensions(1,statusMask,matchMask));
- AliMpIntPair npad0(NofPads(0,statusMask,matchMask));
- AliMpIntPair npad1(NofPads(1,statusMask,matchMask));
+ Long_t npad0(NofPads(0,statusMask,matchMask));
+ Long_t npad1(NofPads(1,statusMask,matchMask));
if ( TMath::Abs( (dim0-dim1).X() ) < 1E-3 )
{
- nx = TMath::Max( npad0.GetFirst(), npad1.GetFirst() );
+ nx = TMath::Max( AliMp::PairFirst(npad0), AliMp::PairFirst(npad1) );
}
else
{
- nx = dim0.X() < dim1.X() ? npad0.GetFirst() : npad1.GetFirst();
+ nx = dim0.X() < dim1.X() ? AliMp::PairFirst(npad0) : AliMp::PairFirst(npad1);
}
if ( TMath::Abs( (dim0-dim1).Y() ) < 1E-3 )
{
- ny = TMath::Max( npad0.GetSecond(), npad1.GetSecond() );
+ ny = TMath::Max( AliMp::PairSecond(npad0), AliMp::PairSecond(npad1) );
}
else
{
- ny = dim0.Y() < dim1.Y() ? npad0.GetSecond() : npad1.GetSecond();
+ ny = dim0.Y() < dim1.Y() ? AliMp::PairSecond(npad0) : AliMp::PairSecond(npad1);
}
- return AliMpIntPair(nx,ny);
+ return AliMp::Pair(nx,ny);
}
//_____________________________________________________________________________
-AliMpIntPair
+Long_t
AliMUONCluster::NofPads(Int_t cathode,
Int_t statusMask, Bool_t matchMask) const
{
Int_t n = Multiplicity(cathode);
if (!n)
{
- return AliMpIntPair(0,0);
+ return 0;
}
Double_t* x = new Double_t[n];
Double_t* y = new Double_t[n];
delete[] x;
delete[] y;
- return AliMpIntPair(cx,cy);
+ return AliMp::Pair(cx,cy);
}
//_____________________________________________________________________________
{
/// Returns the index-th pad
- if (!fPads) return 0x0;
- if ( index < fPads->GetLast()+1 )
+ if (fPads.IsEmpty()) return 0x0;
+ if ( index < fPads.GetLast()+1 )
{
- return static_cast<AliMUONPad*>(fPads->At(index));
+ return static_cast<AliMUONPad*>(fPads.At(index));
}
else
{
- AliError(Form("Requesting index %d out of bounds (%d)",index,fPads->GetLast()));
+ AliError(Form("Requested index %d out of bounds (%d) Mult is %d",index,
+ fPads.GetLast(),Multiplicity()));
+ DumpMe();
}
return 0x0;
}
//_____________________________________________________________________________
void
-AliMUONCluster::Print(Option_t* opt) const
+AliMUONCluster::DumpMe() const
{
/// printout
cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity()
cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
}
- cout << " " << Area() << endl;
- if (fPads)
+ cout << endl;
+// cout << " " << Area() << endl;
+ for (Int_t i = 0; i < fPads.GetSize(); ++i)
{
- fPads->Print("",opt);
+ cout << Form("fPads[%d]=%p",i,fPads.At(i)) << endl;
+ if ( fPads.At(i) ) fPads.At(i)->Print();
}
}
+
//_____________________________________________________________________________
void
-AliMUONCluster::Sort()
+AliMUONCluster::Print(Option_t* opt) const
{
- /// Sort the pad array
- fPads->Sort();
- fIsSorted = kTRUE;
+ /// printout
+ cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity()
+ << "(" << Multiplicity(0) << "," << Multiplicity(1) << ") RawCharge="
+ << RawCharge() << " (" << RawCharge(0) << "," << RawCharge(1)
+ << ") Charge=(" << Charge(0) << "," << Charge(1) <<")";
+ if ( HasPosition() )
+ {
+ cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
+ cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
+ }
+ cout << " " << Area();
+
+ TObjArray* a = static_cast<TObjArray*>(fPads.Clone());
+ a->Sort();
+ a->Print("",opt);
+ delete a;
+}
+
+//_____________________________________________________________________________
+//Bool_t
+//AliMUONCluster::IsEqual(const TObject* obj) const
+//{
+// const AliMUONCluster* c = static_cast<const AliMUONCluster*>(obj);
+// if ( c->Multiplicity() != Multiplicity() ) return kFALSE;
+//
+// for ( Int_t i = 0; i < c->Multiplicity(); ++i )
+// {
+// AliMUONPad* p = c->Pad(i);
+// if ( p->Compare(Pad(i)) ) return kFALSE;
+// }
+// return kTRUE;
+//}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONCluster::Compare(const TObject* obj) const
+{
+ /// Compare two clusters. Comparison is made on position and rawcharge only.
+
+ const AliMUONCluster* cluster = static_cast<const AliMUONCluster*>(obj);
+
+ AliMpArea carea(cluster->Area());
+ AliMpArea area(Area());
+
+ if ( carea.GetPositionX() > area.GetPositionX() )
+ {
+ return 1;
+ }
+ else if ( carea.GetPositionX() < area.GetPositionX() )
+ {
+ return -1;
+ }
+ else
+ {
+ if ( carea.GetPositionY() > area.GetPositionY() )
+ {
+ return 1;
+ }
+ else if ( carea.GetPositionY() < area.GetPositionY() )
+ {
+ return -1;
+ }
+ else
+ {
+ if ( cluster->RawCharge() > RawCharge() )
+ {
+ return 1;
+ }
+ else if ( cluster->RawCharge() < RawCharge() )
+ {
+ return -1;
+ }
+ }
+ }
+ return 0;
}
//_____________________________________________________________________________
/// Remove a pad.
/// As a consequence, some internal information must be updated
- fPads->Remove(pad);
- fPads->Compress();
+ fPads.Remove(pad);
+ fPads.Compress();
+ delete pad;
// update cluster's data
fIsSaturated[0]=fIsSaturated[1]=kFALSE;
fMultiplicity[0]=fMultiplicity[1]=0;
fRawCharge[0]=fRawCharge[1]=0;
- for ( Int_t i = 0; i <= fPads->GetLast(); ++i )
+ for ( Int_t i = 0; i <= fPads.GetLast(); ++i )
{
AliMUONPad* p = Pad(i);
if ( p->IsSaturated() )
++fMultiplicity[p->Cathode()];
fRawCharge[p->Cathode()] += p->Charge();
}
- if (fIsSorted) Sort();
}
//_____________________________________________________________________________