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