]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONCluster.cxx
Adding MUONChamberMaterialBudget.C:
[u/mrichter/AliRoot.git] / MUON / AliMUONCluster.cxx
index c62780665d375b591ff272b33fd6744e8f9a29c2..2ab947e661bf03f99a54c23ba191df8ce51d5af5 100644 (file)
 
 // $Id$
 
+#include <Riostream.h>
+#include <TMath.h>
+#include <TObjArray.h>
+#include <TVirtualPad.h>
+#include <TVirtualX.h>
+
 #include "AliMUONCluster.h"
+#include "AliMUONPad.h"
+
+#include "AliMpEncodePair.h"
 
 #include "AliLog.h"
-#include "AliMUONPad.h"
-#include "TObjArray.h"
-#include "Riostream.h"
-#include "TVirtualPad.h"
-#include "TVirtualX.h"
 
+//-----------------------------------------------------------------------------
 /// \class AliMUONCluster
 ///
 /// A group of adjacent pads
@@ -33,6 +38,7 @@
 ///
 /// \author Laurent Aphecetche
 ///
+//-----------------------------------------------------------------------------
 
 /// \cond CLASSIMP
 ClassImp(AliMUONCluster)
@@ -92,33 +98,33 @@ namespace
 //_____________________________________________________________________________
 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);
 }
 
@@ -127,8 +133,10 @@ AliMUONCluster&
 AliMUONCluster::operator=(const AliMUONCluster& src)
 {
   /// assignement operator
-  AliMUONCluster c(src);
-  c.Copy(*this);
+  if ( this != &src ) 
+  {
+    src.Copy(*this);
+  }
   return *this;
 }
 
@@ -136,25 +144,59 @@ AliMUONCluster::operator=(const AliMUONCluster& src)
 AliMUONCluster::~AliMUONCluster()
 {
   /// dtor : note that we're owner of our pads
-  delete fPads;
 }
 
 //_____________________________________________________________________________
 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();
+}
+
+//_____________________________________________________________________________
+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]);
@@ -163,7 +205,53 @@ AliMUONCluster::AddPad(const AliMUONPad& pad)
   {
     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;
 }
 
 //_____________________________________________________________________________
@@ -188,25 +276,81 @@ AliMUONCluster::Area() const
   }
 
   // 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);
+}
+
+//_____________________________________________________________________________
+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 = fPads;
   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 )
   {
@@ -222,7 +366,21 @@ Float_t
 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;
 }
 
 //_____________________________________________________________________________
@@ -251,6 +409,44 @@ AliMUONCluster::ChargeAsymmetry() const
   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
@@ -310,43 +506,43 @@ AliMUONCluster::Multiplicity(Int_t cathode) 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
 {
@@ -356,7 +552,7 @@ AliMUONCluster::NofPads(Int_t cathode,
   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];
@@ -379,7 +575,7 @@ AliMUONCluster::NofPads(Int_t cathode,
   delete[] x;
   delete[] y;
   
-  return AliMpIntPair(cx,cy);
+  return AliMp::Pair(cx,cy);
 }
 
 //_____________________________________________________________________________
@@ -388,14 +584,16 @@ AliMUONCluster::Pad(Int_t index) const
 {
   /// 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;
 }
@@ -434,35 +632,107 @@ AliMUONCluster::Paint(Option_t*)
 
 //_____________________________________________________________________________
 void
-AliMUONCluster::Print(Option_t* opt) const
+AliMUONCluster::DumpMe() const
 {
   /// printout
   cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity() 
   << "(" << Multiplicity(0) << "," << Multiplicity(1) << ") RawCharge=" 
   << RawCharge() << " (" << RawCharge(0) << "," << RawCharge(1)
-  << " Charge=(" << Charge(0) << "," << Charge(1) <<")";
+  << ") Charge=(" << Charge(0) << "," << Charge(1) <<")";
   if ( HasPosition() )
   {
     cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
     cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
   }
-  AliMpArea a(Area());
-  cout << Form(" Area=(%e,%e,%e,%e)",a.LeftBorder(),a.RightBorder(),
-               a.DownBorder(),a.UpBorder());
   cout << endl;
-  if (fPads) 
+//  cout << " " << Area() << endl;
+  for (Int_t i = 0; i < fPads.GetSize(); ++i) 
   {
-    fPads->Print("",opt);
+    cout << Form("fPads[%d]=%x",i,fPads.At(i)) << endl;
+    if ( fPads.At(i) ) fPads.At(i)->Print();
   }
 }
 
+
 //_____________________________________________________________________________
 void
-AliMUONCluster::Sort()
+AliMUONCluster::Print(Option_t* opt) const
+{
+  /// 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
 {
-  /// Sort the pad array
-  fPads->Sort();
-  fIsSorted = kTRUE;
+  /// 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;
 }
 
 //_____________________________________________________________________________
@@ -472,13 +742,13 @@ AliMUONCluster::RemovePad(AliMUONPad* pad)
   /// Remove a pad. 
   /// As a consequence, some internal information must be updated
   
-  fPads->Remove(pad);
-  fPads->Compress();
+  fPads.Remove(pad);
+  fPads.Compress();
   // 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() ) 
@@ -488,7 +758,6 @@ AliMUONCluster::RemovePad(AliMUONPad* pad)
     ++fMultiplicity[p->Cathode()];
     fRawCharge[p->Cathode()] += p->Charge();
   }
-  if (fIsSorted) Sort();
 }
 
 //_____________________________________________________________________________