]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONPad.cxx
DP: xz CPV-EMC distance filled to TS
[u/mrichter/AliRoot.git] / MUON / AliMUONPad.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
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 **************************************************************************/
15
16 // $Id$
17
18 #include "AliMUONPad.h"
19
20 #include "AliLog.h"
21 #include "AliMpArea.h"
22
23 #include "Riostream.h"
24 #include "TVirtualPad.h"
25 #include "TVirtualX.h"
26 #include "TVector2.h"
27 #include "TMath.h"
28
29 /// \class AliMUONPad
30 ///
31 /// Object gathering information about a hit pad.
32 /// 
33 /// Can be seen as a combination of a Digit (which brings the charge) 
34 /// and an MpPad (which brings location and position)
35 ///
36 /// Also provided are some static functions to compute overlap and
37 /// get neighboring information.
38 ///
39 /// \author Laurent Aphecetche
40
41 /// \cond CLASSIMP
42 ClassImp(AliMUONPad)
43 /// \endcond
44
45 namespace
46 {
47   AliMpArea
48   Intersect(const AliMpArea& a, const AliMpArea& b)
49   { 
50     //
51     // Returns the common part of a and b.
52     //
53     Double_t xmin = TMath::Max(a.LeftBorder(),b.LeftBorder());
54     Double_t xmax = TMath::Min(a.RightBorder(),b.RightBorder());
55     Double_t ymin = TMath::Max(a.DownBorder(),b.DownBorder());
56     Double_t ymax = TMath::Min(a.UpBorder(),b.UpBorder());
57     AliMpArea c( TVector2( (xmin+xmax)/2.0, (ymin+ymax)/2.0 ),
58                  TVector2( (xmax-xmin)/2.0, (ymax-ymin)/2.0 ) );
59         
60     return c;
61   }
62 }
63
64 //_____________________________________________________________________________
65 AliMUONPad::AliMUONPad()
66 :
67 TObject(),
68 fIsSaturated(kFALSE),
69 fIsReal(kFALSE),
70 fClusterId(-1),
71 fCathode(-1),
72 fDetElemId(-1),
73 fDigitIndex(-1),
74 fIx(-1),
75 fIy(-1),
76 fStatus(0),
77 fDimensions(),
78 fPosition(),
79 fCharge(0.0),
80 fChargeBackup(0.0)
81 {
82   /// Default ctor
83   Init(-1,-1,-1,-1,TVector2(0,0),TVector2(0,0),0);
84 }
85
86 //_____________________________________________________________________________
87 AliMUONPad::AliMUONPad(Int_t detElemId, Int_t cathode,
88                        Int_t ix, Int_t iy, Double_t x, Double_t y,
89                        Double_t dx, Double_t dy, Double_t charge)
90 :
91 TObject(),
92 fIsSaturated(kFALSE),
93 fIsReal(kFALSE),
94 fClusterId(-1),
95 fCathode(-1),
96 fDetElemId(-1),
97 fDigitIndex(-1),
98 fIx(-1),
99 fIy(-1),
100 fStatus(0),
101 fDimensions(),
102 fPosition(),
103 fCharge(0.0),
104 fChargeBackup(0.0)
105
106 {
107   /// Normal ctor, using full information
108   Init(detElemId,cathode,ix,iy,TVector2(x,y),TVector2(dx,dy),charge);
109 }
110
111 //_____________________________________________________________________________
112 AliMUONPad::AliMUONPad(Double_t x, Double_t y,
113                        Double_t dx, Double_t dy, Double_t charge)
114 : TObject(),
115 fIsSaturated(kFALSE),
116 fIsReal(kFALSE),
117 fClusterId(-1),
118 fCathode(-1),
119 fDetElemId(-1),
120 fDigitIndex(-1),
121 fIx(-1),
122 fIy(-1),
123 fStatus(0),
124 fDimensions(),
125 fPosition(),
126 fCharge(0.0),
127 fChargeBackup(0.0)
128 {
129   /// Truncated constructor (w/o DE, cath, ix, iy)
130   Init(-1,-1,-1,-1,TVector2(x,y),TVector2(dx,dy),charge);
131 }
132
133 //_____________________________________________________________________________
134 AliMUONPad::AliMUONPad(const TVector2& position, const TVector2& dimensions,
135                        Double_t charge)
136 : TObject(),
137 fIsSaturated(kFALSE),
138 fIsReal(kFALSE),
139 fClusterId(-1),
140 fCathode(-1),
141 fDetElemId(-1),
142 fDigitIndex(-1),
143 fIx(-1),
144 fIy(-1),
145 fStatus(0),
146 fDimensions(),
147 fPosition(),
148 fCharge(0.0),
149 fChargeBackup(0.0)
150 {
151   /// Alternate ctor
152   Init(-1,-1,-1,-1,position,dimensions,charge);
153 }
154
155 //_____________________________________________________________________________
156 Bool_t 
157 AliMUONPad::AreNeighbours(const AliMUONPad& d1, const AliMUONPad& d2) 
158 {
159   /// Whether 2 pads are neighbours or not
160   if ( d1.DetElemId() != d2.DetElemId() || 
161        d1.Cathode() != d2.Cathode() )
162   {
163     return kFALSE;
164   }
165   else
166   {
167     static Double_t precision = 1E-4; // cm
168     static TVector2 precisionAdjustment(-precision,-precision);    
169     return AreOverlapping(d1,d2,precisionAdjustment);
170   }
171 }
172
173 //_____________________________________________________________________________
174 Bool_t
175 AliMUONPad::AreOverlapping(const AliMUONPad& d1, const AliMUONPad& d2,
176                            const TVector2& precision)
177 {
178   /// Checks the overlap between 2 pads.
179   /// The actual overlap is computed not on d1 and d2, but on d1 and d2
180   /// "re-scaled" using the precision vector (conceptually equivalent to 
181   /// d.Dimensions() += precision)
182   ///
183   /// So, if the elements (x,y) of precision are :
184   ///
185   /// - positive, the overlap is "computed" from smaller d1 and d2  
186   ///   which is, modulo the precision, what you would think as a normal
187   ///   overlap calculation
188   /// - negative, overlap is from "bigger" d1 and d2, which is usefull to "tweek"
189   ///   what we call an overlap, e.g. to consider 2 pads touching only by their
190   ///   corners to be overlapping.
191   
192   AliMpArea a1(d1.Position(),d1.Dimensions());
193   AliMpArea a2(d2.Position(),d2.Dimensions());
194   
195   if ( a1.LeftBorder() > a2.RightBorder() - precision.X() ||
196        a1.RightBorder() < a2.LeftBorder() + precision.X() )
197   {
198     return kFALSE;
199   }
200   
201   if ( a1.DownBorder() > a2.UpBorder() - precision.Y() ||
202        a1.UpBorder() < a2.DownBorder() + precision.Y() )
203   {
204     return kFALSE;
205   }
206   return kTRUE;
207 }
208
209 //_____________________________________________________________________________
210 Bool_t
211 AliMUONPad::AreOverlapping(const AliMUONPad& d1, const AliMUONPad& d2,
212                            const TVector2& precision,
213                            AliMpArea& overlapRegion) 
214 {
215   /// Checks the overlap between 2 pads, and returns the overlap area
216   /// 
217   /// See comments on the other AreOverlapping method, too : in this
218   /// method, the overlapRegion does *not* depend on the precision parameter,
219   /// which is only used to decide whether the pads are overlapping, while
220   /// the actual overlap region is computed w/o reference to precision.
221   ///
222   if ( AreOverlapping(d1,d2,precision) )
223   {
224     overlapRegion = Overlap(d1,d2);
225     if ( !overlapRegion.IsValid() )
226     {
227       cerr << "Something is wrong : the 2 pads below are flagged as overlapping"
228       << ", but the overlapRegion is not valid"
229       << endl;
230       d1.Print("corners");
231       d2.Print("corners");
232     }
233     return kTRUE;
234   }
235   return kFALSE;
236 }
237
238 //_____________________________________________________________________________
239 Int_t 
240 AliMUONPad::Compare(const TObject* obj) const
241 {
242   /// Compare 2 pads. 
243   /// Ordering is as complete as possible.
244   
245   const AliMUONPad* pad = static_cast<const AliMUONPad*>(obj);
246     
247   if ( DetElemId() > pad->DetElemId() )
248   {
249     return 1;
250   }
251   else if ( DetElemId() > pad->DetElemId() )
252   {
253     return 1;
254   }
255   else
256   {
257     // same DetElemId...
258     if ( Cathode() > pad->Cathode() )
259     {
260       return 1;
261     }
262     else if ( Cathode() < pad->Cathode() ) 
263     {
264       return -1;
265     }
266     else
267     {
268       // same cathode...
269       if ( Ix() > pad->Ix() )
270       {
271         return 1;
272       }
273       else if ( Ix() < pad->Ix() ) 
274       {
275         return -1;
276       }
277       else
278       {
279         // same ix....
280         if ( Iy() > pad->Iy() )
281         {
282           return 1;
283         }
284         else if ( Iy() < pad->Iy() ) 
285         {
286           return -1;
287         }
288         else
289         {
290           // same iy....
291           if ( X() > pad->X() )
292           {
293             return 1;
294           }
295           else if ( X() < pad->X() )
296           {
297             return -1;
298           }
299           else
300           {
301             // same X
302             if ( Y() > pad->Y() )
303             {
304               return 1;
305             }
306             else if ( Y() < pad->Y() )
307             {
308               return -1;
309             }
310             else
311             {
312               // same Y
313               return ( Charge() < pad->Charge() ) ? -1:1;              
314             }            
315           }          
316         }        
317       }
318     }
319   }
320 }
321
322 //_____________________________________________________________________________
323 Double_t
324 AliMUONPad::Coord(Int_t ixy) const
325 {
326   /// To be friendly and backward compatible with AZ code, which 
327   /// used that kind of coordinate accessing.
328   
329   if ( ixy == 0 ) 
330   {
331     return X();
332   }
333   else if ( ixy == 1 )
334   {
335     return Y();
336   }
337   AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
338   return 0;
339 }
340
341 //_____________________________________________________________________________
342 void 
343 AliMUONPad::Init(Int_t detElemId, Int_t cathode,
344                  Int_t ix, Int_t iy,
345                  const TVector2& position,
346                  const TVector2& dimensions,
347                  Double_t charge)
348 {
349   /// Called by all the ctors
350   fIsSaturated = kFALSE;
351   fIsReal = kTRUE;
352   fDetElemId = detElemId;
353   fCathode = cathode;
354   fIx = ix;
355   fIy = iy;
356   fPosition = position;
357   fDimensions = dimensions;
358   fCharge = charge;
359   fChargeBackup = fCharge;
360   
361   fClusterId = -1;
362   fDigitIndex = -1;
363
364   fStatus = 0;
365 }
366
367 //_____________________________________________________________________________
368 AliMpArea
369 AliMUONPad::Overlap(const AliMUONPad& d1, const AliMUONPad& d2)
370 {  
371   /// Return the overlap region between two pads
372   AliMpArea a1(d1.Position(),d1.Dimensions());
373   AliMpArea a2(d2.Position(),d2.Dimensions());
374   return Intersect(a1,a2);
375 }
376
377
378 //_____________________________________________________________________________
379 void
380 AliMUONPad::Paint(Option_t*)
381 {
382   /// Paint pad on screen
383   TVector2 ll = Position() - Dimensions();
384   TVector2 ur = Position() + Dimensions();
385
386   gPad->PaintBox(ll.X(),ll.Y(),ur.X(),ur.Y());
387 }
388
389 //_____________________________________________________________________________
390 void
391 AliMUONPad::Print(Option_t* opt) const
392 {
393   /// Printout
394   TString sopt(opt);
395   sopt.ToLower();
396   
397   ios_base::fmtflags oldflags = cout.flags();
398   if ( Cathode() >= 0 )
399   {
400     cout << "DetEle " << setw(5) << DetElemId()
401     << " Cath " << setw(2) << Cathode()
402     << " (Ix,Iy)=(" << setw(3) << Ix() << "," << setw(3) << Iy() << ") ";
403   }
404   cout.setf(ios::fixed);
405   cout.precision(6);
406   cout << " (x,y)=(" << setw(9) << X() << "," << setw(9) << Y() << ") "
407   << " (dx,dy)=(" << setw(9) << DX() << "," << setw(9) << DY() << ") "
408   << " Charge=";
409   cout.precision(2);
410   cout << setw(7) << Charge();
411   if ( sopt.Contains("full") )
412   {
413     cout 
414     << " Used=" << (IsUsed()?Form("YES (ClusterId %d)",fClusterId):"NO")
415     << (IsSaturated()?"(S)":"   ")
416     << (IsReal()?"   ":"(V)")
417     << " Status=" << setw(4) << Status()
418     << " ChargeBackup=" << ChargeBackup();
419   }
420   if ( sopt.Contains("corners") )
421   {
422     cout << Form(" (xmin,xmax)=(%e,%e) (ymin,ymax)=(%e,%e)",
423                  X()-DX(),X()+DX(),
424                  Y()-DY(),Y()+DY()) << endl;
425   }
426   cout << endl;
427   cout.flags(oldflags);
428 }
429
430 //_____________________________________________________________________________
431 void 
432 AliMUONPad::SetCoord(Int_t ixy, Double_t coord)
433 {
434   /// Set the pad coordinate (ixy=0 means x, ixy=1 means y)
435   if ( ixy == 0 ) 
436   {
437     fPosition.Set(coord,Y());
438   }
439   else if ( ixy == 1 )
440   {
441     fPosition.Set(X(),coord);
442   }
443   else
444   {
445     AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
446   }
447 }
448
449 //_____________________________________________________________________________
450 void 
451 AliMUONPad::SetSize(Int_t ixy, Double_t size)
452 {
453   /// Set the pad half size (ixy=0 means x half size, ixy=1 means y half size)
454   if ( ixy == 0 ) 
455   {
456     fDimensions.Set(size,DY());
457   }
458   else if ( ixy == 1 )
459   {
460     fDimensions.Set(DX(),size);
461   }
462   else
463   {
464     AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
465   }
466 }
467
468 //_____________________________________________________________________________
469 void 
470 AliMUONPad::Shift(Int_t ixy, Double_t shift)
471 {
472   /// Shift the position by "shift"
473   SetCoord(ixy,Coord(ixy)+shift);
474 }
475
476 //_____________________________________________________________________________
477 Double_t
478 AliMUONPad::Size(Int_t ixy) const
479 {
480   /// Returns the half size along a direction, given by ixy
481   /// (see SetSize for ixy meaning)
482   
483   if ( ixy == 0 ) 
484   {
485     return DX();
486   }
487   else if ( ixy == 1 )
488   {
489     return DY();
490   }
491   AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
492   return 0;
493 }