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