Adding PiKP-only histograms and eliminating a number of switches where histograms...
[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
08bd919e 147// fPads.Delete();
99ccb7f7 148}
149
150//_____________________________________________________________________________
151void
00de388f 152AliMUONCluster::Clear(Option_t*)
153{
08bd919e 154 /// Clear our pad array
155 fPads.Clear();
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
285//_____________________________________________________________________________
00de388f 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//_____________________________________________________________________________
2103dc37 316Bool_t
317AliMUONCluster::IsMonoCathode() const
318{
319 /// Whether we have signals only in one of the two cathodes
320 return (Cathode()<2);
321}
322
323//_____________________________________________________________________________
00de388f 324Int_t
325AliMUONCluster::Cathode() const
326{
327 /// Return the cathode "number" of this cluster :
328 /// 0 if all its pads are on cathode 0
329 /// 1 if all its pads are on cathode 1
330 /// 2 if some pads on cath 0 and some on cath 1
331
332 Int_t cathode(-1);
333 if (Multiplicity(0)>0 && Multiplicity(1)>0)
334 {
335 cathode=2;
336 }
337 else if (Multiplicity(0)>0)
338 {
339 cathode=0;
340 }
341 else if (Multiplicity(1)>0)
342 {
343 cathode=1;
344 }
345
346 return cathode;
347}
348
349//_____________________________________________________________________________
99ccb7f7 350void
351AliMUONCluster::Copy(TObject& obj) const
352{
71a2d3aa 353 ///
354 /// Copy this cluster to (cluster&)obj
355 ///
99ccb7f7 356 TObject::Copy(obj);
357 AliMUONCluster& dest = static_cast<AliMUONCluster&>(obj);
57f3728e 358
359// dest.fPads.Delete();
360 dest.fPads.Clear();
361
362 for ( Int_t i = 0; i <= fPads.GetLast(); ++i )
363 {
364 AliMUONPad* p = static_cast<AliMUONPad*>(fPads.UncheckedAt(i));
365 dest.fPads.AddLast(new AliMUONPad(*p));
366 }
99ccb7f7 367 dest.fHasPosition = fHasPosition;
368 dest.fPosition = fPosition;
369 dest.fPositionError = fPositionError;
370 dest.fHasCharge = fHasCharge;
99ccb7f7 371 dest.fChi2 = fChi2;
372 for ( Int_t i = 0; i < 2; ++i )
373 {
374 dest.fRawCharge[i] = fRawCharge[i];
375 dest.fCharge[i] = fCharge[i];
376 dest.fMultiplicity[i] = fMultiplicity[i];
377 dest.fIsSaturated[i] = fIsSaturated[i];
378 }
379}
380
381//_____________________________________________________________________________
382Float_t
383AliMUONCluster::Charge() const
384{
385 /// Return the average charge over both cathodes
530acd78 386
387 if ( Multiplicity(0) && Multiplicity(1) )
388 {
389 return (Charge(0)+Charge(1))/2.0;
390 }
391 else if ( Multiplicity(0) )
392 {
393 return Charge(0);
394 }
395 else if ( Multiplicity(1) )
396 {
397 return Charge(1);
398 }
399 AliError("Should not be here ?!");
400 return -1.0;
99ccb7f7 401}
402
403//_____________________________________________________________________________
404Float_t
405AliMUONCluster::Charge(Int_t cathode) const
406{
407 /// Returns the charge of a given cathode
408 if ( !fHasCharge ) return RawCharge(cathode);
409
410 if ( cathode == 0 || cathode == 1 )
411 {
412 return fCharge[cathode];
413 }
414 return 0;
415}
416
417//_____________________________________________________________________________
418Float_t
419AliMUONCluster::ChargeAsymmetry() const
420{
421 /// Returns the charge asymmetry
422 if ( Charge() > 0 )
423 {
424 return TMath::Abs(Charge(0)-Charge(1))/Charge();
425 }
426 return 0;
427}
428
429//_____________________________________________________________________________
430TVector2
00de388f 431AliMUONCluster::MaxPadDimensions(Int_t statusMask, Bool_t matchMask) const
432{
433 /// Returns the maximum pad dimensions (half sizes), only considering
434 /// pads matching (or not, depending matchMask) a given mask
435
436 TVector2 cath0(MaxPadDimensions(0,statusMask,matchMask));
437 TVector2 cath1(MaxPadDimensions(1,statusMask,matchMask));
438
439 return TVector2( TMath::Max(cath0.X(),cath1.X()),
440 TMath::Max(cath0.Y(),cath1.Y()) );
441}
442
443//_____________________________________________________________________________
444TVector2
445AliMUONCluster::MaxPadDimensions(Int_t cathode,
446 Int_t statusMask, Bool_t matchMask) const
447{
448 /// Returns the maximum pad dimensions (half sizes), only considering
449 /// pads matching (or not, depending matchMask) a given mask, within a
450 /// given cathode
451
452 Double_t xmax(0);
453 Double_t ymax(0);
454
455 for ( Int_t i = 0; i < Multiplicity(); ++i )
456 {
457 AliMUONPad* pad = Pad(i);
458 if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
459 {
460 xmax = TMath::Max(xmax,pad->DX());
461 ymax = TMath::Max(ymax,pad->DY());
462 }
463 }
464 return TVector2(xmax,ymax);
465}
466
467//_____________________________________________________________________________
468TVector2
99ccb7f7 469AliMUONCluster::MinPadDimensions(Int_t statusMask, Bool_t matchMask) const
470{
471 /// Returns the minimum pad dimensions (half sizes), only considering
472 /// pads matching (or not, depending matchMask) a given mask
473
474 TVector2 cath0(MinPadDimensions(0,statusMask,matchMask));
475 TVector2 cath1(MinPadDimensions(1,statusMask,matchMask));
476
477 return TVector2( TMath::Min(cath0.X(),cath1.X()),
478 TMath::Min(cath0.Y(),cath1.Y()) );
479}
480
481//_____________________________________________________________________________
482TVector2
483AliMUONCluster::MinPadDimensions(Int_t cathode,
484 Int_t statusMask, Bool_t matchMask) const
485{
486 /// Returns the minimum pad dimensions (half sizes), only considering
487 /// pads matching (or not, depending matchMask) a given mask, within a
488 /// given cathode
489
490 Double_t xmin(1E9);
491 Double_t ymin(1E9);
492
493 for ( Int_t i = 0; i < Multiplicity(); ++i )
494 {
495 AliMUONPad* pad = Pad(i);
496 if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
497 {
498 xmin = TMath::Min(xmin,pad->DX());
499 ymin = TMath::Min(ymin,pad->DY());
500 }
501 }
502 return TVector2(xmin,ymin);
503}
504
505//_____________________________________________________________________________
506Int_t
507AliMUONCluster::Multiplicity() const
508{
509 /// Returns the total number of pads in this cluster
510 return Multiplicity(0)+Multiplicity(1);
511}
512
513//_____________________________________________________________________________
514Int_t
515AliMUONCluster::Multiplicity(Int_t cathode) const
516{
517 /// Returns the number of pads in this cluster, in the given cathode
518 if ( cathode == 0 || cathode == 1 )
519 {
520 return fMultiplicity[cathode];
521 }
522 return 0;
523}
524
525//_____________________________________________________________________________
168e9c4d 526Long_t
99ccb7f7 527AliMUONCluster::NofPads(Int_t statusMask, Bool_t matchMask) const
528{
529 /// Number of pads satisfying (or not, depending matchMask) a
168e9c4d 530 /// given mask
99ccb7f7 531
532 Int_t nx, ny;
533
534 TVector2 dim0(MinPadDimensions(0,statusMask,matchMask));
535 TVector2 dim1(MinPadDimensions(1,statusMask,matchMask));
536
168e9c4d 537 Long_t npad0(NofPads(0,statusMask,matchMask));
538 Long_t npad1(NofPads(1,statusMask,matchMask));
99ccb7f7 539
540 if ( TMath::Abs( (dim0-dim1).X() ) < 1E-3 )
541 {
168e9c4d 542 nx = TMath::Max( AliMp::PairFirst(npad0), AliMp::PairFirst(npad1) );
99ccb7f7 543 }
544 else
545 {
168e9c4d 546 nx = dim0.X() < dim1.X() ? AliMp::PairFirst(npad0) : AliMp::PairFirst(npad1);
99ccb7f7 547 }
548
549 if ( TMath::Abs( (dim0-dim1).Y() ) < 1E-3 )
550 {
168e9c4d 551 ny = TMath::Max( AliMp::PairSecond(npad0), AliMp::PairSecond(npad1) );
99ccb7f7 552 }
553 else
554 {
168e9c4d 555 ny = dim0.Y() < dim1.Y() ? AliMp::PairSecond(npad0) : AliMp::PairSecond(npad1);
99ccb7f7 556 }
557
168e9c4d 558 return AliMp::Pair(nx,ny);
99ccb7f7 559}
560
561//_____________________________________________________________________________
168e9c4d 562Long_t
99ccb7f7 563AliMUONCluster::NofPads(Int_t cathode,
564 Int_t statusMask, Bool_t matchMask) const
565{
566 /// Number of pads of a given cathode, satisfying (or not,
567 /// depending matchMask) a given mask
568
569 Int_t n = Multiplicity(cathode);
570 if (!n)
571 {
168e9c4d 572 return 0;
99ccb7f7 573 }
574 Double_t* x = new Double_t[n];
575 Double_t* y = new Double_t[n];
576 Int_t np(0);
577
578 for ( Int_t i = 0; i < Multiplicity(); ++i )
579 {
580 AliMUONPad* pad = Pad(i);
581 if ( ShouldUsePad(*pad,cathode,statusMask,matchMask) )
582 {
583 x[np] = pad->X();
584 y[np] = pad->Y();
585 ++np;
586 }
587 }
588
589 Int_t cx = Unique(np,x,0.01);
590 Int_t cy = Unique(np,y,0.01);
591
592 delete[] x;
593 delete[] y;
594
168e9c4d 595 return AliMp::Pair(cx,cy);
99ccb7f7 596}
597
598//_____________________________________________________________________________
599AliMUONPad*
600AliMUONCluster::Pad(Int_t index) const
601{
602 /// Returns the index-th pad
603
e0de1dd9 604 if (fPads.IsEmpty()) return 0x0;
605 if ( index < fPads.GetLast()+1 )
99ccb7f7 606 {
e0de1dd9 607 return static_cast<AliMUONPad*>(fPads.At(index));
99ccb7f7 608 }
609 else
610 {
00de388f 611 AliError(Form("Requested index %d out of bounds (%d) Mult is %d",index,
e0de1dd9 612 fPads.GetLast(),Multiplicity()));
00de388f 613 DumpMe();
99ccb7f7 614 }
615 return 0x0;
616}
617
618
619//_____________________________________________________________________________
620void
621AliMUONCluster::Paint(Option_t*)
622{
623 /// Paint this cluster
624 if (!Multiplicity()) return;
625
626 AliMpArea area(Area());
627
628 gPad->Range(area.LeftBorder(),area.DownBorder(),area.RightBorder(),area.UpBorder());
629
630 gVirtualX->SetFillStyle(0);
631
632 gVirtualX->SetLineColor(2);
633 gVirtualX->SetLineWidth(4);
634 for ( Int_t i = 0; i < Multiplicity(); ++i)
635 {
636 AliMUONPad* pad = Pad(i);
637 if ( pad->Cathode() == 0 ) pad->Paint();
638 }
639
640 gVirtualX->SetLineColor(4);
641 gVirtualX->SetLineWidth(2);
642 for ( Int_t i = 0; i < Multiplicity(); ++i)
643 {
644 AliMUONPad* pad = Pad(i);
645 if ( pad->Cathode() == 1 ) pad->Paint();
646 }
647
648}
649
650//_____________________________________________________________________________
651void
00de388f 652AliMUONCluster::DumpMe() const
653{
654 /// printout
655 cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity()
656 << "(" << Multiplicity(0) << "," << Multiplicity(1) << ") RawCharge="
657 << RawCharge() << " (" << RawCharge(0) << "," << RawCharge(1)
658 << ") Charge=(" << Charge(0) << "," << Charge(1) <<")";
659 if ( HasPosition() )
660 {
661 cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
662 cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
663 }
664 cout << endl;
665// cout << " " << Area() << endl;
e0de1dd9 666 for (Int_t i = 0; i < fPads.GetSize(); ++i)
00de388f 667 {
1130977f 668 cout << Form("fPads[%d]=%p",i,fPads.At(i)) << endl;
e0de1dd9 669 if ( fPads.At(i) ) fPads.At(i)->Print();
670 }
00de388f 671}
672
673
674//_____________________________________________________________________________
675void
99ccb7f7 676AliMUONCluster::Print(Option_t* opt) const
677{
678 /// printout
679 cout << "Cluster Id " << GetUniqueID() << " npads=" << Multiplicity()
680 << "(" << Multiplicity(0) << "," << Multiplicity(1) << ") RawCharge="
681 << RawCharge() << " (" << RawCharge(0) << "," << RawCharge(1)
97d5019e 682 << ") Charge=(" << Charge(0) << "," << Charge(1) <<")";
99ccb7f7 683 if ( HasPosition() )
684 {
685 cout << " (x,y)=(" << Position().X() << "," << Position().Y() << ")";
686 cout << " (errX,errY)=(" << PositionError().X() << "," << PositionError().Y() << ")";
687 }
00de388f 688 cout << " " << Area();
e0de1dd9 689
690 TObjArray* a = static_cast<TObjArray*>(fPads.Clone());
691 a->Sort();
692 a->Print("",opt);
693 delete a;
99ccb7f7 694}
695
696//_____________________________________________________________________________
00de388f 697//Bool_t
698//AliMUONCluster::IsEqual(const TObject* obj) const
699//{
700// const AliMUONCluster* c = static_cast<const AliMUONCluster*>(obj);
701// if ( c->Multiplicity() != Multiplicity() ) return kFALSE;
702//
703// for ( Int_t i = 0; i < c->Multiplicity(); ++i )
704// {
705// AliMUONPad* p = c->Pad(i);
706// if ( p->Compare(Pad(i)) ) return kFALSE;
707// }
708// return kTRUE;
709//}
710
711//_____________________________________________________________________________
712Int_t
713AliMUONCluster::Compare(const TObject* obj) const
99ccb7f7 714{
00de388f 715 /// Compare two clusters. Comparison is made on position and rawcharge only.
716
717 const AliMUONCluster* cluster = static_cast<const AliMUONCluster*>(obj);
718
719 AliMpArea carea(cluster->Area());
720 AliMpArea area(Area());
721
6e97fbb8 722 if ( carea.GetPositionX() > area.GetPositionX() )
00de388f 723 {
724 return 1;
725 }
6e97fbb8 726 else if ( carea.GetPositionX() < area.GetPositionX() )
00de388f 727 {
728 return -1;
729 }
730 else
731 {
6e97fbb8 732 if ( carea.GetPositionY() > area.GetPositionY() )
00de388f 733 {
734 return 1;
735 }
6e97fbb8 736 else if ( carea.GetPositionY() < area.GetPositionY() )
00de388f 737 {
738 return -1;
739 }
740 else
741 {
742 if ( cluster->RawCharge() > RawCharge() )
743 {
744 return 1;
745 }
746 else if ( cluster->RawCharge() < RawCharge() )
747 {
748 return -1;
749 }
750 }
751 }
752 return 0;
99ccb7f7 753}
754
755//_____________________________________________________________________________
756void
757AliMUONCluster::RemovePad(AliMUONPad* pad)
758{
759 /// Remove a pad.
760 /// As a consequence, some internal information must be updated
761
e0de1dd9 762 fPads.Remove(pad);
763 fPads.Compress();
57f3728e 764 delete pad;
99ccb7f7 765 // update cluster's data
766 fIsSaturated[0]=fIsSaturated[1]=kFALSE;
767 fMultiplicity[0]=fMultiplicity[1]=0;
768 fRawCharge[0]=fRawCharge[1]=0;
e0de1dd9 769 for ( Int_t i = 0; i <= fPads.GetLast(); ++i )
99ccb7f7 770 {
771 AliMUONPad* p = Pad(i);
772 if ( p->IsSaturated() )
773 {
774 fIsSaturated[p->Cathode()] = kTRUE;
775 }
776 ++fMultiplicity[p->Cathode()];
777 fRawCharge[p->Cathode()] += p->Charge();
778 }
99ccb7f7 779}
780
781//_____________________________________________________________________________
782Float_t
783AliMUONCluster::RawCharge() const
784{
785 /// Returns the raw average charge
786 return (RawCharge(0)+RawCharge(1))/2.0;
787}
788
789//_____________________________________________________________________________
790Float_t
791AliMUONCluster::RawCharge(Int_t cathode) const
792{
793 /// Returns the average charge of a given cathode
794 if ( cathode == 0 || cathode == 1 )
795 {
796 return fRawCharge[cathode];
797 }
798 return 0;
799}
800
801//_____________________________________________________________________________
802Float_t
803AliMUONCluster::RawChargeAsymmetry() const
804{
805 /// Returns the raw charge asymmetry
806 if ( RawCharge() > 0 )
807 {
808 return TMath::Abs(RawCharge(0)-RawCharge(1))/RawCharge();
809 }
810 return 0;
811}