]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONCluster.cxx
Fixing bug in generating error messages, where the wrong DDL was being indicated.
[u/mrichter/AliRoot.git] / MUON / AliMUONCluster.cxx
CommitLineData
99ccb7f7 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
9edefa04 18#include <Riostream.h>
19#include <TMath.h>
20#include <TObjArray.h>
21#include <TVirtualPad.h>
22#include <TVirtualX.h>
23
99ccb7f7 24#include "AliMUONCluster.h"
168e9c4d 25#include "AliMUONPad.h"
26
27#include "AliMpEncodePair.h"
99ccb7f7 28
29#include "AliLog.h"
99ccb7f7 30
3d1463c8 31//-----------------------------------------------------------------------------
99ccb7f7 32/// \class AliMUONCluster
33///
34/// A group of adjacent pads
35///
36/// Besides holding an internal array of AliMUONPads, this object
37/// also computes some global characteristics for that pad sets.
38///
39/// \author Laurent Aphecetche
40///
3d1463c8 41//-----------------------------------------------------------------------------
99ccb7f7 42
43/// \cond CLASSIMP
44ClassImp(AliMUONCluster)
45/// \endcond
46
47namespace
48{
49 //___________________________________________________________________________
50 Bool_t
51 ShouldUsePad(const AliMUONPad& pad,
52 Int_t cathode, Int_t statusMask, Bool_t matchMask)
53 {
54
55 // FIXME : we should only use >=0 status, so we can fully
56 // use masking possibility ?
57 if ( pad.Status() < 0 ) return kFALSE;
58
59 if ( pad.Cathode() == cathode && pad.IsReal() && !pad.IsSaturated() )
60 {
61 Bool_t test = ( ( pad.Status() & statusMask ) != 0 );
62 if ( !statusMask )
63 {
64 test = ( pad.Status() == 0 );
65 }
66 if ( ( test && matchMask ) || ( !test && !matchMask ) )
67 {
68 return kTRUE;
69 }
70 }
71 return kFALSE;
72 }
73
74 //___________________________________________________________________________
75 Int_t Unique(Int_t n, Double_t* array, Double_t precision)
76 {
77 /// Return the number of *different* elements in array
78 /// where different is up to precision
79 /// Note that we assume that n is >= 1
80
81 Int_t count(1);
82
83 Int_t* index = new Int_t[n];
84
85 TMath::Sort(n,array,index);
86
87 for ( Int_t i = 1; i < n; ++i )
88 {
89 if ( array[index[i]] - array[index[i-1]] < -precision ) ++count;
90 }
91
92 delete[] index;
93
94 return count;
95 }
96}
97
98//_____________________________________________________________________________
99AliMUONCluster::AliMUONCluster()
100: TObject(),
e0de1dd9 101fPads(),
99ccb7f7 102fHasPosition(kFALSE),
103fPosition(1E9,1E9),
104fPositionError(1E9,1E9),
105fHasCharge(kFALSE),
00de388f 106fChi2(0)
99ccb7f7 107{
108 /// ctor
109 fMultiplicity[0]=fMultiplicity[1]=0;
110 fRawCharge[0]=fRawCharge[1]=0;
111 fCharge[0]=fCharge[1]=0;
112 fIsSaturated[0]=fIsSaturated[1]=kFALSE;
e0de1dd9 113 fPads.SetOwner(kTRUE);
99ccb7f7 114}
115
116//_____________________________________________________________________________
117AliMUONCluster::AliMUONCluster(const AliMUONCluster& src)
118: TObject(src),
e0de1dd9 119fPads(),
99ccb7f7 120fHasPosition(kFALSE),
121fPosition(1E9,1E9),
122fPositionError(1E9,1E9),
123fHasCharge(kFALSE),
00de388f 124fChi2(0)
99ccb7f7 125{
126 /// copy ctor
e0de1dd9 127 fPads.SetOwner(kTRUE);
99ccb7f7 128 src.Copy(*this);
129}
130
131//_____________________________________________________________________________
132AliMUONCluster&
133AliMUONCluster::operator=(const AliMUONCluster& src)
134{
135 /// assignement operator
0c8556b9 136 if ( this != &src )
137 {
138 src.Copy(*this);
139 }
99ccb7f7 140 return *this;
141}
142
143//_____________________________________________________________________________
144AliMUONCluster::~AliMUONCluster()
145{
146 /// dtor : note that we're owner of our pads
57f3728e 147// fPads.Delete();
99ccb7f7 148}
149
150//_____________________________________________________________________________
151void
00de388f 152AliMUONCluster::Clear(Option_t*)
153{
154 /// Clear our pad array
e0de1dd9 155 fPads.Clear();
57f3728e 156// fPads.Delete();
00de388f 157}
158
159//_____________________________________________________________________________
160Bool_t
161AliMUONCluster::Contains(const AliMUONPad& pad) const
162{
163 /// Whether this cluster contains the pad
e0de1dd9 164 if (fPads.IsEmpty()) return kFALSE;
165
00de388f 166 for ( Int_t i = 0; i < Multiplicity(); ++i )
167 {
168 AliMUONPad* p = Pad(i);
169 if ( pad.Compare(p) == 0 ) return kTRUE;
170 }
171 return kFALSE;
172}
173
174//_____________________________________________________________________________
175void
176AliMUONCluster::AddCluster(const AliMUONCluster& cluster)
177{
178 /// Add all the pads for cluster to this one
179 for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
180 {
181 AliMUONPad* p = cluster.Pad(i);
182 if ( Contains(*p) )
183 {
184 AliError("I already got this pad : ");
185 StdoutToAliError(p->Print(););
186 AliFatal("");
187 }
188 AddPad(*p);
189 }
190
191}
192
193//_____________________________________________________________________________
194AliMUONPad*
99ccb7f7 195AliMUONCluster::AddPad(const AliMUONPad& pad)
196{
197 /// Add a pad to our pad array, and update some internal information
198 /// accordingly.
e0de1dd9 199
99ccb7f7 200 AliMUONPad* p = new AliMUONPad(pad);
e0de1dd9 201 fPads.AddLast(p);
99ccb7f7 202 p->SetClusterId(GetUniqueID());
203 Int_t cathode = p->Cathode();
204 ++(fMultiplicity[cathode]);
205 fRawCharge[cathode] += p->Charge();
206 if ( p->IsSaturated() )
207 {
208 fIsSaturated[p->Cathode()]=kTRUE;
209 }
00de388f 210 return p;
211}
212
213//___________________________________________________________________________
214TString
215AliMUONCluster::AsString() const
216{
217 /// Return a string containing a compact form of the pad list
218 TString s(Form("NPADS(%d,%d)",Multiplicity(0),Multiplicity(1)));
219
220 for (Int_t i = 0; i < Multiplicity(); ++i )
221 {
222 AliMUONPad* p = Pad(i);
223 s += Form(" (%d,%d,%d) ",p->Cathode(),p->Ix(),p->Iy());
224 }
225 return s;
226}
227
228
229//___________________________________________________________________________
230Bool_t
231AliMUONCluster::AreOverlapping(const AliMUONCluster& c1, const AliMUONCluster& c2)
232{
233 /// Whether the two clusters overlap
234
235 static Double_t precision = 1E-4; // cm
236 static TVector2 precisionAdjustment(precision,precision);
237
238 for ( Int_t i1 = 0; i1 < c1.Multiplicity(); ++i1 )
239 {
240 AliMUONPad* p1 = c1.Pad(i1);
241
242 for ( Int_t i2 = 0; i2 < c2.Multiplicity(); ++i2 )
243 {
244 AliMUONPad* p2 = c2.Pad(i2);
245 // Note: we use negative precision numbers, meaning
246 // the area of the pads will be *increased* by these small numbers
247 // prior to check the overlap by the AreOverlapping method,
248 // so pads touching only by the corners will be considered as
249 // overlapping.
250 if ( AliMUONPad::AreOverlapping(*p1,*p2,precisionAdjustment) )
251 {
252 return kTRUE;
253 }
254 }
255 }
256 return kFALSE;
99ccb7f7 257}
258
259//_____________________________________________________________________________
260AliMpArea
261AliMUONCluster::Area() const
262{
263 /// Return the geometrical area covered by this cluster
264
265 // Start by finding the (x,y) limits of this cluster
266 TVector2 lowerLeft(1E9,1E9);
267 TVector2 upperRight(-1E9,-1E9);
268
269 for ( Int_t i = 0; i < Multiplicity(); ++i )
270 {
271 AliMUONPad* pad = Pad(i);
272 TVector2 ll = pad->Position() - pad->Dimensions();
273 TVector2 ur = pad->Position() + pad->Dimensions();
274 lowerLeft.Set( TMath::Min(ll.X(),lowerLeft.X()),
275 TMath::Min(ll.Y(),lowerLeft.Y()) );
276 upperRight.Set( TMath::Max(ur.X(),upperRight.X()),
277 TMath::Max(ur.Y(),upperRight.Y()) );
278 }
279
280 // then construct the area from those limits
6e97fbb8 281 return AliMpArea((lowerLeft+upperRight).X()/2,(lowerLeft+upperRight).Y()/2,
282 (upperRight-lowerLeft).X()/2, (upperRight-lowerLeft).Y()/2);
99ccb7f7 283}
284
00de388f 285//_____________________________________________________________________________
286AliMpArea
287AliMUONCluster::Area(Int_t cathode) const
288{
289 /// Return the geometrical area covered by this cluster's pads on
290 /// a given cathode
291
292 // Start by finding the (x,y) limits of this cluster
293 TVector2 lowerLeft(1E9,1E9);
294 TVector2 upperRight(-1E9,-1E9);
295
cd1f0e79 296 for ( Int_t i = 0; i < Multiplicity(); ++i )
00de388f 297 {
298 AliMUONPad* pad = Pad(i);
cd1f0e79 299 if ( pad->Cathode() == cathode )
300 {
301 TVector2 ll = pad->Position() - pad->Dimensions();
302 TVector2 ur = pad->Position() + pad->Dimensions();
303 lowerLeft.Set( TMath::Min(ll.X(),lowerLeft.X()),
304 TMath::Min(ll.Y(),lowerLeft.Y()) );
305 upperRight.Set( TMath::Max(ur.X(),upperRight.X()),
306 TMath::Max(ur.Y(),upperRight.Y()) );
307 }
00de388f 308 }
309
310 // then construct the area from those limits
6e97fbb8 311 return AliMpArea((lowerLeft+upperRight).X()/2,(lowerLeft+upperRight).Y()/2,
312 (upperRight-lowerLeft).X()/2, (upperRight-lowerLeft).Y()/2);
00de388f 313}
314
315//_____________________________________________________________________________
316Int_t
317AliMUONCluster::Cathode() const
318{
319 /// Return the cathode "number" of this cluster :
320 /// 0 if all its pads are on cathode 0
321 /// 1 if all its pads are on cathode 1
322 /// 2 if some pads on cath 0 and some on cath 1
323
324 Int_t cathode(-1);
325 if (Multiplicity(0)>0 && Multiplicity(1)>0)
326 {
327 cathode=2;
328 }
329 else if (Multiplicity(0)>0)
330 {
331 cathode=0;
332 }
333 else if (Multiplicity(1)>0)
334 {
335 cathode=1;
336 }
337
338 return cathode;
339}
340
99ccb7f7 341//_____________________________________________________________________________
342void
343AliMUONCluster::Copy(TObject& obj) const
344{
71a2d3aa 345 ///
346 /// Copy this cluster to (cluster&)obj
347 ///
99ccb7f7 348 TObject::Copy(obj);
349 AliMUONCluster& dest = static_cast<AliMUONCluster&>(obj);
57f3728e 350
351// dest.fPads.Delete();
352 dest.fPads.Clear();
353
354 for ( Int_t i = 0; i <= fPads.GetLast(); ++i )
355 {
356 AliMUONPad* p = static_cast<AliMUONPad*>(fPads.UncheckedAt(i));
357 dest.fPads.AddLast(new AliMUONPad(*p));
358 }
99ccb7f7 359 dest.fHasPosition = fHasPosition;
360 dest.fPosition = fPosition;
361 dest.fPositionError = fPositionError;
362 dest.fHasCharge = fHasCharge;
99ccb7f7 363 dest.fChi2 = fChi2;
364 for ( Int_t i = 0; i < 2; ++i )
365 {
366 dest.fRawCharge[i] = fRawCharge[i];
367 dest.fCharge[i] = fCharge[i];
368 dest.fMultiplicity[i] = fMultiplicity[i];
369 dest.fIsSaturated[i] = fIsSaturated[i];
370 }
371}
372
373//_____________________________________________________________________________
374Float_t
375AliMUONCluster::Charge() const
376{
377 /// Return the average charge over both cathodes
530acd78 378
379 if ( Multiplicity(0) && Multiplicity(1) )
380 {
381 return (Charge(0)+Charge(1))/2.0;
382 }
383 else if ( Multiplicity(0) )
384 {
385 return Charge(0);
386 }
387 else if ( Multiplicity(1) )
388 {
389 return Charge(1);
390 }
391 AliError("Should not be here ?!");
392 return -1.0;
99ccb7f7 393}
394
395//_____________________________________________________________________________
396Float_t
397AliMUONCluster::Charge(Int_t cathode) const
398{
399 /// Returns the charge of a given cathode
400 if ( !fHasCharge ) return RawCharge(cathode);
401
402 if ( cathode == 0 || cathode == 1 )
403 {
404 return fCharge[cathode];
405 }
406 return 0;
407}
408
409//_____________________________________________________________________________
410Float_t
411AliMUONCluster::ChargeAsymmetry() const
412{
413 /// Returns the charge asymmetry
414 if ( Charge() > 0 )
415 {
416 return TMath::Abs(Charge(0)-Charge(1))/Charge();
417 }
418 return 0;
419}
420
00de388f 421//_____________________________________________________________________________
422TVector2
423AliMUONCluster::MaxPadDimensions(Int_t statusMask, Bool_t matchMask) const
424{
425 /// Returns the maximum pad dimensions (half sizes), only considering
426 /// pads matching (or not, depending matchMask) a given mask
427
428 TVector2 cath0(MaxPadDimensions(0,statusMask,matchMask));
429 TVector2 cath1(MaxPadDimensions(1,statusMask,matchMask));
430
431 return TVector2( TMath::Max(cath0.X(),cath1.X()),
432 TMath::Max(cath0.Y(),cath1.Y()) );
433}
434
435//_____________________________________________________________________________
436TVector2
437AliMUONCluster::MaxPadDimensions(Int_t cathode,
438 Int_t statusMask, Bool_t matchMask) const
439{
440 /// Returns the maximum pad dimensions (half sizes), only considering
441 /// pads matching (or not, depending matchMask) a given mask, within a
442 /// given cathode
443
444 Double_t xmax(0);
445 Double_t ymax(0);
446
447 for ( Int_t i = 0; i < Multiplicity(); ++i )
448 {
449 AliMUONPad* pad = Pad(i);
450 if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
451 {
452 xmax = TMath::Max(xmax,pad->DX());
453 ymax = TMath::Max(ymax,pad->DY());
454 }
455 }
456 return TVector2(xmax,ymax);
457}
458
99ccb7f7 459//_____________________________________________________________________________
460TVector2
461AliMUONCluster::MinPadDimensions(Int_t statusMask, Bool_t matchMask) const
462{
463 /// Returns the minimum pad dimensions (half sizes), only considering
464 /// pads matching (or not, depending matchMask) a given mask
465
466 TVector2 cath0(MinPadDimensions(0,statusMask,matchMask));
467 TVector2 cath1(MinPadDimensions(1,statusMask,matchMask));
468
469 return TVector2( TMath::Min(cath0.X(),cath1.X()),
470 TMath::Min(cath0.Y(),cath1.Y()) );
471}
472
473//_____________________________________________________________________________
474TVector2
475AliMUONCluster::MinPadDimensions(Int_t cathode,
476 Int_t statusMask, Bool_t matchMask) const
477{
478 /// Returns the minimum pad dimensions (half sizes), only considering
479 /// pads matching (or not, depending matchMask) a given mask, within a
480 /// given cathode
481
482 Double_t xmin(1E9);
483 Double_t ymin(1E9);
484
485 for ( Int_t i = 0; i < Multiplicity(); ++i )
486 {
487 AliMUONPad* pad = Pad(i);
488 if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
489 {
490 xmin = TMath::Min(xmin,pad->DX());
491 ymin = TMath::Min(ymin,pad->DY());
492 }
493 }
494 return TVector2(xmin,ymin);
495}
496
497//_____________________________________________________________________________
498Int_t
499AliMUONCluster::Multiplicity() const
500{
501 /// Returns the total number of pads in this cluster
502 return Multiplicity(0)+Multiplicity(1);
503}
504
505//_____________________________________________________________________________
506Int_t
507AliMUONCluster::Multiplicity(Int_t cathode) const
508{
509 /// Returns the number of pads in this cluster, in the given cathode
510 if ( cathode == 0 || cathode == 1 )
511 {
512 return fMultiplicity[cathode];
513 }
514 return 0;
515}
516
517//_____________________________________________________________________________
168e9c4d 518Long_t
99ccb7f7 519AliMUONCluster::NofPads(Int_t statusMask, Bool_t matchMask) const
520{
521 /// Number of pads satisfying (or not, depending matchMask) a
168e9c4d 522 /// given mask
99ccb7f7 523
524 Int_t nx, ny;
525
526 TVector2 dim0(MinPadDimensions(0,statusMask,matchMask));
527 TVector2 dim1(MinPadDimensions(1,statusMask,matchMask));
528
168e9c4d 529 Long_t npad0(NofPads(0,statusMask,matchMask));
530 Long_t npad1(NofPads(1,statusMask,matchMask));
99ccb7f7 531
532 if ( TMath::Abs( (dim0-dim1).X() ) < 1E-3 )
533 {
168e9c4d 534 nx = TMath::Max( AliMp::PairFirst(npad0), AliMp::PairFirst(npad1) );
99ccb7f7 535 }
536 else
537 {
168e9c4d 538 nx = dim0.X() < dim1.X() ? AliMp::PairFirst(npad0) : AliMp::PairFirst(npad1);
99ccb7f7 539 }
540
541 if ( TMath::Abs( (dim0-dim1).Y() ) < 1E-3 )
542 {
168e9c4d 543 ny = TMath::Max( AliMp::PairSecond(npad0), AliMp::PairSecond(npad1) );
99ccb7f7 544 }
545 else
546 {
168e9c4d 547 ny = dim0.Y() < dim1.Y() ? AliMp::PairSecond(npad0) : AliMp::PairSecond(npad1);
99ccb7f7 548 }
549
168e9c4d 550 return AliMp::Pair(nx,ny);
99ccb7f7 551}
552
553//_____________________________________________________________________________
168e9c4d 554Long_t
99ccb7f7 555AliMUONCluster::NofPads(Int_t cathode,
556 Int_t statusMask, Bool_t matchMask) const
557{
558 /// Number of pads of a given cathode, satisfying (or not,
559 /// depending matchMask) a given mask
560
561 Int_t n = Multiplicity(cathode);
562 if (!n)
563 {
168e9c4d 564 return 0;
99ccb7f7 565 }
566 Double_t* x = new Double_t[n];
567 Double_t* y = new Double_t[n];
568 Int_t np(0);
569
570 for ( Int_t i = 0; i < Multiplicity(); ++i )
571 {
572 AliMUONPad* pad = Pad(i);
573 if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
574 {
575 x[np] = pad->X();
576 y[np] = pad->Y();
577 ++np;
578 }
579 }
580
581 Int_t cx = Unique(np,x,0.01);
582 Int_t cy = Unique(np,y,0.01);
583
584 delete[] x;
585 delete[] y;
586
168e9c4d 587 return AliMp::Pair(cx,cy);
99ccb7f7 588}
589
590//_____________________________________________________________________________
591AliMUONPad*
592AliMUONCluster::Pad(Int_t index) const
593{
594 /// Returns the index-th pad
595
e0de1dd9 596 if (fPads.IsEmpty()) return 0x0;
597 if ( index < fPads.GetLast()+1 )
99ccb7f7 598 {
e0de1dd9 599 return static_cast<AliMUONPad*>(fPads.At(index));
99ccb7f7 600 }
601 else
602 {
00de388f 603 AliError(Form("Requested index %d out of bounds (%d) Mult is %d",index,
e0de1dd9 604 fPads.GetLast(),Multiplicity()));
00de388f 605 DumpMe();
99ccb7f7 606 }
607 return 0x0;
608}
609
610
611//_____________________________________________________________________________
612void
613AliMUONCluster::Paint(Option_t*)
614{
615 /// Paint this cluster
616 if (!Multiplicity()) return;
617
618 AliMpArea area(Area());
619
620 gPad->Range(area.LeftBorder(),area.DownBorder(),area.RightBorder(),area.UpBorder());
621
622 gVirtualX->SetFillStyle(0);
623
624 gVirtualX->SetLineColor(2);
625 gVirtualX->SetLineWidth(4);
626 for ( Int_t i = 0; i < Multiplicity(); ++i)
627 {
628 AliMUONPad* pad = Pad(i);
629 if ( pad->Cathode() == 0 ) pad->Paint();
630 }
631
632 gVirtualX->SetLineColor(4);
633 gVirtualX->SetLineWidth(2);
634 for ( Int_t i = 0; i < Multiplicity(); ++i)
635 {
636 AliMUONPad* pad = Pad(i);
637 if ( pad->Cathode() == 1 ) pad->Paint();
638 }
639
640}
641
00de388f 642//_____________________________________________________________________________
643void
644AliMUONCluster::DumpMe() const
645{
646 /// printout
647 cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity()
648 << "(" << Multiplicity(0) << "," << Multiplicity(1) << ") RawCharge="
649 << RawCharge() << " (" << RawCharge(0) << "," << RawCharge(1)
650 << ") Charge=(" << Charge(0) << "," << Charge(1) <<")";
651 if ( HasPosition() )
652 {
653 cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
654 cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
655 }
656 cout << endl;
657// cout << " " << Area() << endl;
e0de1dd9 658 for (Int_t i = 0; i < fPads.GetSize(); ++i)
00de388f 659 {
e0de1dd9 660 cout << Form("fPads[%d]=%x",i,fPads.At(i)) << endl;
661 if ( fPads.At(i) ) fPads.At(i)->Print();
662 }
00de388f 663}
664
665
99ccb7f7 666//_____________________________________________________________________________
667void
668AliMUONCluster::Print(Option_t* opt) const
669{
670 /// printout
671 cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity()
672 << "(" << Multiplicity(0) << "," << Multiplicity(1) << ") RawCharge="
673 << RawCharge() << " (" << RawCharge(0) << "," << RawCharge(1)
97d5019e 674 << ") Charge=(" << Charge(0) << "," << Charge(1) <<")";
99ccb7f7 675 if ( HasPosition() )
676 {
677 cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
678 cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
679 }
00de388f 680 cout << " " << Area();
e0de1dd9 681
682 TObjArray* a = static_cast<TObjArray*>(fPads.Clone());
683 a->Sort();
684 a->Print("",opt);
685 delete a;
99ccb7f7 686}
687
688//_____________________________________________________________________________
00de388f 689//Bool_t
690//AliMUONCluster::IsEqual(const TObject* obj) const
691//{
692// const AliMUONCluster* c = static_cast<const AliMUONCluster*>(obj);
693// if ( c->Multiplicity() != Multiplicity() ) return kFALSE;
694//
695// for ( Int_t i = 0; i < c->Multiplicity(); ++i )
696// {
697// AliMUONPad* p = c->Pad(i);
698// if ( p->Compare(Pad(i)) ) return kFALSE;
699// }
700// return kTRUE;
701//}
702
703//_____________________________________________________________________________
704Int_t
705AliMUONCluster::Compare(const TObject* obj) const
99ccb7f7 706{
00de388f 707 /// Compare two clusters. Comparison is made on position and rawcharge only.
708
709 const AliMUONCluster* cluster = static_cast<const AliMUONCluster*>(obj);
710
711 AliMpArea carea(cluster->Area());
712 AliMpArea area(Area());
713
6e97fbb8 714 if ( carea.GetPositionX() > area.GetPositionX() )
00de388f 715 {
716 return 1;
717 }
6e97fbb8 718 else if ( carea.GetPositionX() < area.GetPositionX() )
00de388f 719 {
720 return -1;
721 }
722 else
723 {
6e97fbb8 724 if ( carea.GetPositionY() > area.GetPositionY() )
00de388f 725 {
726 return 1;
727 }
6e97fbb8 728 else if ( carea.GetPositionY() < area.GetPositionY() )
00de388f 729 {
730 return -1;
731 }
732 else
733 {
734 if ( cluster->RawCharge() > RawCharge() )
735 {
736 return 1;
737 }
738 else if ( cluster->RawCharge() < RawCharge() )
739 {
740 return -1;
741 }
742 }
743 }
744 return 0;
99ccb7f7 745}
746
747//_____________________________________________________________________________
748void
749AliMUONCluster::RemovePad(AliMUONPad* pad)
750{
751 /// Remove a pad.
752 /// As a consequence, some internal information must be updated
753
e0de1dd9 754 fPads.Remove(pad);
755 fPads.Compress();
57f3728e 756 delete pad;
99ccb7f7 757 // update cluster's data
758 fIsSaturated[0]=fIsSaturated[1]=kFALSE;
759 fMultiplicity[0]=fMultiplicity[1]=0;
760 fRawCharge[0]=fRawCharge[1]=0;
e0de1dd9 761 for ( Int_t i = 0; i <= fPads.GetLast(); ++i )
99ccb7f7 762 {
763 AliMUONPad* p = Pad(i);
764 if ( p->IsSaturated() )
765 {
766 fIsSaturated[p->Cathode()] = kTRUE;
767 }
768 ++fMultiplicity[p->Cathode()];
769 fRawCharge[p->Cathode()] += p->Charge();
770 }
99ccb7f7 771}
772
773//_____________________________________________________________________________
774Float_t
775AliMUONCluster::RawCharge() const
776{
777 /// Returns the raw average charge
778 return (RawCharge(0)+RawCharge(1))/2.0;
779}
780
781//_____________________________________________________________________________
782Float_t
783AliMUONCluster::RawCharge(Int_t cathode) const
784{
785 /// Returns the average charge of a given cathode
786 if ( cathode == 0 || cathode == 1 )
787 {
788 return fRawCharge[cathode];
789 }
790 return 0;
791}
792
793//_____________________________________________________________________________
794Float_t
795AliMUONCluster::RawChargeAsymmetry() const
796{
797 /// Returns the raw charge asymmetry
798 if ( RawCharge() > 0 )
799 {
800 return TMath::Abs(RawCharge(0)-RawCharge(1))/RawCharge();
801 }
802 return 0;
803}