]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONPad.cxx
Adding links to README pages
[u/mrichter/AliRoot.git] / MUON / AliMUONPad.cxx
CommitLineData
4b6f2cee 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
42ClassImp(AliMUONPad)
43/// \endcond
44
45namespace
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//_____________________________________________________________________________
65AliMUONPad::AliMUONPad()
66:
67TObject(),
68fIsSaturated(kFALSE),
69fIsReal(kFALSE),
70fClusterId(-1),
71fCathode(-1),
72fDetElemId(-1),
73fDigitIndex(-1),
74fIx(-1),
75fIy(-1),
76fStatus(0),
77fDimensions(),
78fPosition(),
79fCharge(0.0),
80fChargeBackup(0.0)
81{
82 /// Default ctor
83 Init(-1,-1,-1,-1,TVector2(0,0),TVector2(0,0),0);
84}
85
86//_____________________________________________________________________________
87AliMUONPad::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:
91TObject(),
92fIsSaturated(kFALSE),
93fIsReal(kFALSE),
94fClusterId(-1),
95fCathode(-1),
96fDetElemId(-1),
97fDigitIndex(-1),
98fIx(-1),
99fIy(-1),
100fStatus(0),
101fDimensions(),
102fPosition(),
103fCharge(0.0),
104fChargeBackup(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//_____________________________________________________________________________
112AliMUONPad::AliMUONPad(Double_t x, Double_t y,
113 Double_t dx, Double_t dy, Double_t charge)
114: TObject(),
115fIsSaturated(kFALSE),
116fIsReal(kFALSE),
117fClusterId(-1),
118fCathode(-1),
119fDetElemId(-1),
120fDigitIndex(-1),
121fIx(-1),
122fIy(-1),
123fStatus(0),
124fDimensions(),
125fPosition(),
126fCharge(0.0),
127fChargeBackup(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//_____________________________________________________________________________
134AliMUONPad::AliMUONPad(const TVector2& position, const TVector2& dimensions,
135 Double_t charge)
136: TObject(),
137fIsSaturated(kFALSE),
138fIsReal(kFALSE),
139fClusterId(-1),
140fCathode(-1),
141fDetElemId(-1),
142fDigitIndex(-1),
143fIx(-1),
144fIy(-1),
145fStatus(0),
146fDimensions(),
147fPosition(),
148fCharge(0.0),
149fChargeBackup(0.0)
150{
151 /// Alternate ctor
152 Init(-1,-1,-1,-1,position,dimensions,charge);
153}
154
71a2d3aa 155//_____________________________________________________________________________
156AliMUONPad::~AliMUONPad()
157{
158/// Dtor
159}
160
4b6f2cee 161//_____________________________________________________________________________
162Bool_t
163AliMUONPad::AreNeighbours(const AliMUONPad& d1, const AliMUONPad& d2)
164{
165 /// Whether 2 pads are neighbours or not
166 if ( d1.DetElemId() != d2.DetElemId() ||
167 d1.Cathode() != d2.Cathode() )
168 {
169 return kFALSE;
170 }
171 else
172 {
173 static Double_t precision = 1E-4; // cm
174 static TVector2 precisionAdjustment(-precision,-precision);
175 return AreOverlapping(d1,d2,precisionAdjustment);
176 }
177}
178
179//_____________________________________________________________________________
180Bool_t
181AliMUONPad::AreOverlapping(const AliMUONPad& d1, const AliMUONPad& d2,
182 const TVector2& precision)
183{
184 /// Checks the overlap between 2 pads.
185 /// The actual overlap is computed not on d1 and d2, but on d1 and d2
186 /// "re-scaled" using the precision vector (conceptually equivalent to
187 /// d.Dimensions() += precision)
188 ///
189 /// So, if the elements (x,y) of precision are :
190 ///
191 /// - positive, the overlap is "computed" from smaller d1 and d2
192 /// which is, modulo the precision, what you would think as a normal
193 /// overlap calculation
194 /// - negative, overlap is from "bigger" d1 and d2, which is usefull to "tweek"
195 /// what we call an overlap, e.g. to consider 2 pads touching only by their
196 /// corners to be overlapping.
197
198 AliMpArea a1(d1.Position(),d1.Dimensions());
199 AliMpArea a2(d2.Position(),d2.Dimensions());
200
201 if ( a1.LeftBorder() > a2.RightBorder() - precision.X() ||
202 a1.RightBorder() < a2.LeftBorder() + precision.X() )
203 {
204 return kFALSE;
205 }
206
207 if ( a1.DownBorder() > a2.UpBorder() - precision.Y() ||
208 a1.UpBorder() < a2.DownBorder() + precision.Y() )
209 {
210 return kFALSE;
211 }
212 return kTRUE;
213}
214
215//_____________________________________________________________________________
216Bool_t
217AliMUONPad::AreOverlapping(const AliMUONPad& d1, const AliMUONPad& d2,
218 const TVector2& precision,
219 AliMpArea& overlapRegion)
220{
221 /// Checks the overlap between 2 pads, and returns the overlap area
222 ///
223 /// See comments on the other AreOverlapping method, too : in this
224 /// method, the overlapRegion does *not* depend on the precision parameter,
225 /// which is only used to decide whether the pads are overlapping, while
226 /// the actual overlap region is computed w/o reference to precision.
227 ///
228 if ( AreOverlapping(d1,d2,precision) )
229 {
230 overlapRegion = Overlap(d1,d2);
231 if ( !overlapRegion.IsValid() )
232 {
233 cerr << "Something is wrong : the 2 pads below are flagged as overlapping"
234 << ", but the overlapRegion is not valid"
235 << endl;
236 d1.Print("corners");
237 d2.Print("corners");
238 }
239 return kTRUE;
240 }
241 return kFALSE;
242}
243
244//_____________________________________________________________________________
245Int_t
246AliMUONPad::Compare(const TObject* obj) const
247{
248 /// Compare 2 pads.
249 /// Ordering is as complete as possible.
250
251 const AliMUONPad* pad = static_cast<const AliMUONPad*>(obj);
252
8f473fdb 253 if (DetElemId() < 0)
254 {
4bd6a200 255 // AZ - For "pixels" from MLEM cluster finder
8f473fdb 256 // we only sort on charge
4bd6a200 257 if (Charge() == pad->Charge()) return 0;
258 return ( Charge() < pad->Charge() ) ? 1:-1;
259 }
260
4b6f2cee 261 if ( DetElemId() > pad->DetElemId() )
262 {
263 return 1;
264 }
2a055915 265 else if ( DetElemId() < pad->DetElemId() )
4b6f2cee 266 {
8f473fdb 267 return -1;
4b6f2cee 268 }
269 else
270 {
271 // same DetElemId...
272 if ( Cathode() > pad->Cathode() )
273 {
274 return 1;
275 }
276 else if ( Cathode() < pad->Cathode() )
277 {
278 return -1;
279 }
280 else
281 {
282 // same cathode...
283 if ( Ix() > pad->Ix() )
284 {
285 return 1;
286 }
287 else if ( Ix() < pad->Ix() )
288 {
289 return -1;
290 }
291 else
292 {
293 // same ix....
294 if ( Iy() > pad->Iy() )
295 {
296 return 1;
297 }
298 else if ( Iy() < pad->Iy() )
299 {
300 return -1;
301 }
302 else
303 {
304 // same iy....
305 if ( X() > pad->X() )
306 {
307 return 1;
308 }
309 else if ( X() < pad->X() )
310 {
311 return -1;
312 }
313 else
314 {
315 // same X
316 if ( Y() > pad->Y() )
317 {
318 return 1;
319 }
320 else if ( Y() < pad->Y() )
321 {
322 return -1;
323 }
324 else
325 {
326 // same Y
8f473fdb 327 if ( Charge() < pad->Charge() )
328 {
329 return -1;
330 }
331 else if ( Charge() > pad->Charge() )
332 {
333 return 1;
334 }
335 else
336 {
337 return 0;
338 }
339 }
4b6f2cee 340 }
341 }
342 }
343 }
344 }
8f473fdb 345 return 0;
4b6f2cee 346}
347
348//_____________________________________________________________________________
349Double_t
350AliMUONPad::Coord(Int_t ixy) const
351{
352 /// To be friendly and backward compatible with AZ code, which
353 /// used that kind of coordinate accessing.
354
355 if ( ixy == 0 )
356 {
357 return X();
358 }
359 else if ( ixy == 1 )
360 {
361 return Y();
362 }
363 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
364 return 0;
365}
366
367//_____________________________________________________________________________
368void
369AliMUONPad::Init(Int_t detElemId, Int_t cathode,
370 Int_t ix, Int_t iy,
371 const TVector2& position,
372 const TVector2& dimensions,
373 Double_t charge)
374{
375 /// Called by all the ctors
376 fIsSaturated = kFALSE;
377 fIsReal = kTRUE;
378 fDetElemId = detElemId;
379 fCathode = cathode;
380 fIx = ix;
381 fIy = iy;
382 fPosition = position;
383 fDimensions = dimensions;
384 fCharge = charge;
385 fChargeBackup = fCharge;
386
387 fClusterId = -1;
388 fDigitIndex = -1;
389
390 fStatus = 0;
391}
392
393//_____________________________________________________________________________
394AliMpArea
395AliMUONPad::Overlap(const AliMUONPad& d1, const AliMUONPad& d2)
396{
397 /// Return the overlap region between two pads
398 AliMpArea a1(d1.Position(),d1.Dimensions());
399 AliMpArea a2(d2.Position(),d2.Dimensions());
400 return Intersect(a1,a2);
401}
402
403
404//_____________________________________________________________________________
405void
406AliMUONPad::Paint(Option_t*)
407{
408 /// Paint pad on screen
409 TVector2 ll = Position() - Dimensions();
410 TVector2 ur = Position() + Dimensions();
411
412 gPad->PaintBox(ll.X(),ll.Y(),ur.X(),ur.Y());
413}
414
415//_____________________________________________________________________________
416void
417AliMUONPad::Print(Option_t* opt) const
418{
419 /// Printout
420 TString sopt(opt);
421 sopt.ToLower();
422
423 ios_base::fmtflags oldflags = cout.flags();
424 if ( Cathode() >= 0 )
425 {
426 cout << "DetEle " << setw(5) << DetElemId()
427 << " Cath " << setw(2) << Cathode()
428 << " (Ix,Iy)=(" << setw(3) << Ix() << "," << setw(3) << Iy() << ") ";
429 }
430 cout.setf(ios::fixed);
431 cout.precision(6);
432 cout << " (x,y)=(" << setw(9) << X() << "," << setw(9) << Y() << ") "
433 << " (dx,dy)=(" << setw(9) << DX() << "," << setw(9) << DY() << ") "
434 << " Charge=";
435 cout.precision(2);
436 cout << setw(7) << Charge();
437 if ( sopt.Contains("full") )
438 {
439 cout
440 << " Used=" << (IsUsed()?Form("YES (ClusterId %d)",fClusterId):"NO")
441 << (IsSaturated()?"(S)":" ")
442 << (IsReal()?" ":"(V)")
443 << " Status=" << setw(4) << Status()
444 << " ChargeBackup=" << ChargeBackup();
445 }
446 if ( sopt.Contains("corners") )
447 {
448 cout << Form(" (xmin,xmax)=(%e,%e) (ymin,ymax)=(%e,%e)",
449 X()-DX(),X()+DX(),
450 Y()-DY(),Y()+DY()) << endl;
451 }
452 cout << endl;
4bd6a200 453 cout.precision(6); // reset to default precision
4b6f2cee 454 cout.flags(oldflags);
455}
456
457//_____________________________________________________________________________
458void
459AliMUONPad::SetCoord(Int_t ixy, Double_t coord)
460{
461 /// Set the pad coordinate (ixy=0 means x, ixy=1 means y)
462 if ( ixy == 0 )
463 {
464 fPosition.Set(coord,Y());
465 }
466 else if ( ixy == 1 )
467 {
468 fPosition.Set(X(),coord);
469 }
470 else
471 {
472 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
473 }
474}
475
476//_____________________________________________________________________________
477void
478AliMUONPad::SetSize(Int_t ixy, Double_t size)
479{
480 /// Set the pad half size (ixy=0 means x half size, ixy=1 means y half size)
481 if ( ixy == 0 )
482 {
483 fDimensions.Set(size,DY());
484 }
485 else if ( ixy == 1 )
486 {
487 fDimensions.Set(DX(),size);
488 }
489 else
490 {
491 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
492 }
493}
494
495//_____________________________________________________________________________
496void
497AliMUONPad::Shift(Int_t ixy, Double_t shift)
498{
499 /// Shift the position by "shift"
500 SetCoord(ixy,Coord(ixy)+shift);
501}
502
503//_____________________________________________________________________________
504Double_t
505AliMUONPad::Size(Int_t ixy) const
506{
507 /// Returns the half size along a direction, given by ixy
508 /// (see SetSize for ixy meaning)
509
510 if ( ixy == 0 )
511 {
512 return DX();
513 }
514 else if ( ixy == 1 )
515 {
516 return DY();
517 }
518 AliError(Form("Incorrect coordinates index %d (only 0,1 are valid)",ixy));
519 return 0;
520}