1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 #include "AliMUONPad.h"
21 #include "AliMpArea.h"
23 #include "Riostream.h"
24 #include "TVirtualPad.h"
25 #include "TVirtualX.h"
29 //-----------------------------------------------------------------------------
32 /// Object gathering information about a hit pad.
34 /// Can be seen as a combination of a Digit (which brings the charge)
35 /// and an MpPad (which brings location and position)
37 /// Also provided are some static functions to compute overlap and
38 /// get neighboring information.
40 /// \author Laurent Aphecetche
41 //-----------------------------------------------------------------------------
50 Intersect(const AliMpArea& a, const AliMpArea& b)
53 // Returns the common part of a and b.
55 Double_t xmin = TMath::Max(a.LeftBorder(),b.LeftBorder());
56 Double_t xmax = TMath::Min(a.RightBorder(),b.RightBorder());
57 Double_t ymin = TMath::Max(a.DownBorder(),b.DownBorder());
58 Double_t ymax = TMath::Min(a.UpBorder(),b.UpBorder());
59 AliMpArea c( TVector2( (xmin+xmax)/2.0, (ymin+ymax)/2.0 ),
60 TVector2( (xmax-xmin)/2.0, (ymax-ymin)/2.0 ) );
66 //_____________________________________________________________________________
67 AliMUONPad::AliMUONPad()
84 Init(-1,-1,-1,-1,TVector2(0,0),TVector2(0,0),0);
87 //_____________________________________________________________________________
88 AliMUONPad::AliMUONPad(Int_t detElemId, Int_t cathode,
89 Int_t ix, Int_t iy, Double_t x, Double_t y,
90 Double_t dx, Double_t dy, Double_t charge)
107 /// Normal ctor, using full information
108 Init(detElemId,cathode,ix,iy,TVector2(x,y),TVector2(dx,dy),charge);
111 //_____________________________________________________________________________
112 AliMUONPad::AliMUONPad(Double_t x, Double_t y,
113 Double_t dx, Double_t dy, Double_t charge)
115 fIsSaturated(kFALSE),
128 /// Truncated constructor (w/o DE, cath, ix, iy)
129 Init(-1,-1,-1,-1,TVector2(x,y),TVector2(dx,dy),charge);
132 //_____________________________________________________________________________
133 AliMUONPad::AliMUONPad(const TVector2& position, const TVector2& dimensions,
136 fIsSaturated(kFALSE),
150 Init(-1,-1,-1,-1,position,dimensions,charge);
153 //_____________________________________________________________________________
154 AliMUONPad::~AliMUONPad()
159 //_____________________________________________________________________________
161 AliMUONPad::AreNeighbours(const AliMUONPad& d1, const AliMUONPad& d2)
163 /// Whether 2 pads are neighbours or not
164 if ( d1.DetElemId() != d2.DetElemId() ||
165 d1.Cathode() != d2.Cathode() )
171 static Double_t precision = 1E-4; // cm
172 static TVector2 precisionAdjustment(-precision,-precision);
173 return AreOverlapping(d1,d2,precisionAdjustment);
177 //_____________________________________________________________________________
179 AliMUONPad::AreOverlapping(const AliMUONPad& d1, const AliMUONPad& d2,
180 const TVector2& precision)
182 /// Checks the overlap between 2 pads.
183 /// The actual overlap is computed not on d1 and d2, but on d1 and d2
184 /// "re-scaled" using the precision vector (conceptually equivalent to
185 /// d.Dimensions() += precision)
187 /// So, if the elements (x,y) of precision are :
189 /// - positive, the overlap is "computed" from smaller d1 and d2
190 /// which is, modulo the precision, what you would think as a normal
191 /// overlap calculation
192 /// - negative, overlap is from "bigger" d1 and d2, which is usefull to "tweek"
193 /// what we call an overlap, e.g. to consider 2 pads touching only by their
194 /// corners to be overlapping.
196 AliMpArea a1(d1.Position(),d1.Dimensions());
197 AliMpArea a2(d2.Position(),d2.Dimensions());
199 if ( a1.LeftBorder() > a2.RightBorder() - precision.X() ||
200 a1.RightBorder() < a2.LeftBorder() + precision.X() )
205 if ( a1.DownBorder() > a2.UpBorder() - precision.Y() ||
206 a1.UpBorder() < a2.DownBorder() + precision.Y() )
213 //_____________________________________________________________________________
215 AliMUONPad::AreOverlapping(const AliMUONPad& d1, const AliMUONPad& d2,
216 const TVector2& precision,
217 AliMpArea& overlapRegion)
219 /// Checks the overlap between 2 pads, and returns the overlap area
221 /// See comments on the other AreOverlapping method, too : in this
222 /// method, the overlapRegion does *not* depend on the precision parameter,
223 /// which is only used to decide whether the pads are overlapping, while
224 /// the actual overlap region is computed w/o reference to precision.
226 if ( AreOverlapping(d1,d2,precision) )
228 overlapRegion = Overlap(d1,d2);
229 if ( !overlapRegion.IsValid() )
231 cerr << "Something is wrong : the 2 pads below are flagged as overlapping"
232 << ", but the overlapRegion is not valid"
242 //_____________________________________________________________________________
244 AliMUONPad::Compare(const TObject* obj) const
247 /// Ordering is as complete as possible.
249 const AliMUONPad* pad = static_cast<const AliMUONPad*>(obj);
253 // AZ - For "pixels" from MLEM cluster finder
254 // we only sort on charge
255 if (Charge() == pad->Charge()) return 0;
256 return ( Charge() < pad->Charge() ) ? 1:-1;
259 if ( DetElemId() > pad->DetElemId() )
263 else if ( DetElemId() < pad->DetElemId() )
270 if ( Cathode() > pad->Cathode() )
274 else if ( Cathode() < pad->Cathode() )
281 if ( Ix() > pad->Ix() )
285 else if ( Ix() < pad->Ix() )
292 if ( Iy() > pad->Iy() )
296 else if ( Iy() < pad->Iy() )
303 if ( X() > pad->X() )
307 else if ( X() < pad->X() )
314 if ( Y() > pad->Y() )
318 else if ( Y() < pad->Y() )
325 if ( Charge() < pad->Charge() )
329 else if ( Charge() > pad->Charge() )
346 //_____________________________________________________________________________
348 AliMUONPad::Coord(Int_t ixy) const
350 /// To be friendly and backward compatible with AZ code, which
351 /// used that kind of coordinate accessing.
361 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
365 //_____________________________________________________________________________
367 AliMUONPad::Init(Int_t detElemId, Int_t cathode,
369 const TVector2& position,
370 const TVector2& dimensions,
373 /// Called by all the ctors
374 fIsSaturated = kFALSE;
376 fDetElemId = detElemId;
380 fPosition = position;
381 fDimensions = dimensions;
383 fChargeBackup = fCharge;
390 //_____________________________________________________________________________
392 AliMUONPad::Overlap(const AliMUONPad& d1, const AliMUONPad& d2)
394 /// Return the overlap region between two pads
395 AliMpArea a1(d1.Position(),d1.Dimensions());
396 AliMpArea a2(d2.Position(),d2.Dimensions());
397 return Intersect(a1,a2);
401 //_____________________________________________________________________________
403 AliMUONPad::Paint(Option_t*)
405 /// Paint pad on screen
406 TVector2 ll = Position() - Dimensions();
407 TVector2 ur = Position() + Dimensions();
409 gPad->PaintBox(ll.X(),ll.Y(),ur.X(),ur.Y());
412 //_____________________________________________________________________________
414 AliMUONPad::Print(Option_t* opt) const
420 ios_base::fmtflags oldflags = cout.flags();
421 if ( Cathode() >= 0 )
423 cout << "DetEle " << setw(5) << DetElemId()
424 << " Cath " << setw(2) << Cathode()
425 << " (Ix,Iy)=(" << setw(3) << Ix() << "," << setw(3) << Iy() << ") ";
427 cout.setf(ios::fixed);
429 cout << " (x,y)=(" << setw(9) << X() << "," << setw(9) << Y() << ") "
430 << " (dx,dy)=(" << setw(9) << DX() << "," << setw(9) << DY() << ") "
433 cout << setw(7) << Charge();
434 if ( sopt.Contains("full") )
437 << " Used=" << (IsUsed()?Form("YES (ClusterId %d)",fClusterId):"NO")
438 << (IsSaturated()?"(S)":" ")
439 << (IsReal()?" ":"(V)")
440 << " Status=" << setw(4) << Status()
441 << " ChargeBackup=" << ChargeBackup();
443 if ( sopt.Contains("corners") )
445 cout << Form(" (xmin,xmax)=(%e,%e) (ymin,ymax)=(%e,%e)",
447 Y()-DY(),Y()+DY()) << endl;
450 cout.precision(6); // reset to default precision
451 cout.flags(oldflags);
454 //_____________________________________________________________________________
456 AliMUONPad::SetCoord(Int_t ixy, Double_t coord)
458 /// Set the pad coordinate (ixy=0 means x, ixy=1 means y)
461 fPosition.Set(coord,Y());
465 fPosition.Set(X(),coord);
469 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
473 //_____________________________________________________________________________
475 AliMUONPad::SetSize(Int_t ixy, Double_t size)
477 /// Set the pad half size (ixy=0 means x half size, ixy=1 means y half size)
480 fDimensions.Set(size,DY());
484 fDimensions.Set(DX(),size);
488 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
492 //_____________________________________________________________________________
494 AliMUONPad::Shift(Int_t ixy, Double_t shift)
496 /// Shift the position by "shift"
497 SetCoord(ixy,Coord(ixy)+shift);
500 //_____________________________________________________________________________
502 AliMUONPad::Size(Int_t ixy) const
504 /// Returns the half size along a direction, given by ixy
505 /// (see SetSize for ixy meaning)
515 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));