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 "AliMUONPreClusterFinder.h"
19 :
20 : #include "AliCodeTimer.h"
21 :
22 : #include "AliMUONCluster.h"
23 : #include "AliMUONPad.h"
24 : #include "AliMUONVDigit.h"
25 : #include "AliMUONVDigitStore.h"
26 :
27 : #include "AliMpArea.h"
28 : #include "AliMpConstants.h"
29 : #include "AliMpVSegmentation.h"
30 :
31 : #include "AliLog.h"
32 :
33 : #include <Riostream.h>
34 : #include <TObjArray.h>
35 : #include <TVector2.h>
36 :
37 : //-----------------------------------------------------------------------------
38 : /// \class AliMUONPreClusterFinder
39 : ///
40 : /// Implementation of AliMUONVClusterFinder
41 : ///
42 : /// This class simply find adjacent pads to form clusters
43 : ///
44 : /// \author Laurent Aphecetche
45 : //-----------------------------------------------------------------------------
46 :
47 18 : ClassImp(AliMUONPreClusterFinder)
48 :
49 : //_____________________________________________________________________________
50 : AliMUONPreClusterFinder::AliMUONPreClusterFinder()
51 2 : : AliMUONVClusterFinder(),
52 2 : fClusters("AliMUONCluster"),
53 2 : fPads(0x0),
54 2 : fDetElemId(0),
55 2 : fArea(),
56 2 : fShouldAbort(kFALSE)
57 10 : {
58 : /// ctor
59 4 : }
60 :
61 : //_____________________________________________________________________________
62 : AliMUONPreClusterFinder::~AliMUONPreClusterFinder()
63 12 : {
64 : /// dtor : note we're owner of the clusters, but not of the pads
65 6 : }
66 :
67 : //_____________________________________________________________________________
68 : Bool_t
69 : AliMUONPreClusterFinder::UsePad(const AliMUONPad& pad)
70 : {
71 : /// Add a pad to the list of pads to be considered
72 0 : if ( pad.DetElemId() != fDetElemId )
73 : {
74 0 : AliError(Form("Cannot add pad from DE %d to this cluster finder which is "
75 : "currently dealing with DE %d",pad.DetElemId(),fDetElemId));
76 0 : return kFALSE;
77 : }
78 :
79 0 : fPads[pad.Cathode()]->Add(new AliMUONPad(pad));
80 : // FIXME: should set the ClusterId of that new pad to be -1
81 0 : return kTRUE;
82 0 : }
83 :
84 : //_____________________________________________________________________________
85 : Bool_t
86 : AliMUONPreClusterFinder::Prepare(Int_t detElemId,
87 : TObjArray* pads[2],
88 : const AliMpArea& area)
89 : {
90 : /// Prepare for clustering, by giving access to segmentations and digit lists
91 :
92 288 : fClusters.Delete();
93 :
94 144 : fPads = pads;
95 144 : fDetElemId = detElemId;
96 144 : fArea = area;
97 :
98 144 : fShouldAbort = kFALSE;
99 :
100 144 : return kTRUE;
101 : }
102 :
103 : //_____________________________________________________________________________
104 : void
105 : AliMUONPreClusterFinder::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
106 : {
107 : /// Add a pad to a cluster
108 :
109 3460 : if ( cluster.IsMonoCathode() && cluster.Multiplicity() > 199 )
110 : {
111 : /// FIXME : we should at that point really find a better way to remove "bad" preclusters,
112 : /// like e.g. computing the charge dispersion (the lower, the most probably we have noise cluster)
113 : /// and/or mean charge per pad (if too close to LowestPadCharge, again that's a noise cluster...
114 : /// *BUT* this needs carefull testing !
115 0 : fShouldAbort = kTRUE;
116 0 : return;
117 : }
118 :
119 1324 : AliMUONPad* addedPad = cluster.AddPad(*pad);
120 :
121 1324 : Int_t cathode = pad->Cathode();
122 1324 : TObjArray& padArray = *fPads[cathode];
123 : // WARNING: this Remove method uses the AliMUONPad::IsEqual if that method is
124 : // present (otherwise just compares pointers) : so that one must be correct
125 : // if implemented !
126 1324 : TObject* o = padArray.Remove(pad);
127 : // if (!o)
128 : // {
129 : // AliFatal("Oups. Could not remove pad from pads to consider. Aborting as anyway "
130 : // " we'll get an infinite loop. Please check the AliMUONPad::IsEqual method"
131 : // " as the first suspect for failed remove");
132 : // }
133 2648 : delete o;
134 :
135 1324 : TIter next(&padArray);
136 : AliMUONPad* testPad;
137 :
138 7512 : while ( ( testPad = static_cast<AliMUONPad*>(next())))
139 : {
140 3540 : if ( AliMUONPad::AreNeighbours(*testPad,*addedPad) )
141 : {
142 996 : AddPad(cluster,testPad);
143 : }
144 : }
145 2648 : }
146 :
147 : //_____________________________________________________________________________
148 : Bool_t
149 : AreOverlapping(const AliMUONPad& pad, const AliMUONCluster& cluster)
150 : {
151 : /// Whether the pad overlaps with the cluster
152 :
153 : static Double_t precision = 1E-4; // cm
154 516 : static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
155 2133 : for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
156 : {
157 930 : AliMUONPad* testPad = cluster.Pad(i);
158 : // Note: we use negative precision numbers, meaning
159 : // the area of the pads will be *increased* by these small numbers
160 : // prior to check the overlap by the AreOverlapping method,
161 : // so pads touching only by the corners will be considered as
162 : // overlapping.
163 930 : if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
164 : {
165 164 : return kTRUE;
166 : }
167 766 : }
168 91 : return kFALSE;
169 255 : }
170 :
171 : //_____________________________________________________________________________
172 : AliMUONPad*
173 : AliMUONPreClusterFinder::GetNextPad(Int_t cathode) const
174 : {
175 : /// Return the next unused pad of given cathode, which is within fArea
176 :
177 904 : TIter next(fPads[cathode]);
178 :
179 452 : if ( !fArea.IsValid() )
180 : {
181 904 : return static_cast<AliMUONPad*>(next());
182 : }
183 : else
184 : {
185 : AliMUONPad* pad;
186 0 : while ( ( pad = static_cast<AliMUONPad*>(next())) )
187 : {
188 0 : AliMpArea padArea(pad->X(), pad->Y(), pad->DX(), pad->DY());
189 :
190 0 : if (fArea.Overlap(padArea)) return pad;
191 :
192 0 : }
193 0 : return 0x0;
194 : }
195 452 : }
196 :
197 : //_____________________________________________________________________________
198 : AliMUONCluster*
199 : AliMUONPreClusterFinder::NewCluster()
200 : {
201 : /// Create a new (empty) cluster
202 328 : Int_t id = fClusters.GetLast()+1;
203 164 : AliMUONCluster* cluster = new (fClusters[id]) AliMUONCluster;
204 164 : cluster->SetUniqueID(id);
205 164 : return cluster;
206 0 : }
207 :
208 : //_____________________________________________________________________________
209 : void
210 : AliMUONPreClusterFinder::RemoveCluster(AliMUONCluster* cluster)
211 : {
212 : /// Remove a cluster
213 : /// Note that we are *not* releasing the pads, so they won't be used further on
214 0 : fClusters.Remove(cluster);
215 0 : fClusters.Compress();
216 0 : }
217 :
218 : //_____________________________________________________________________________
219 : AliMUONCluster*
220 : AliMUONPreClusterFinder::NextCluster()
221 : {
222 : /// Builds the next cluster, and returns it.
223 :
224 : // Start a new cluster
225 :
226 616 : AliMUONPad* pad = GetNextPad(0);
227 :
228 : AliMUONCluster* cluster(0x0);
229 :
230 308 : if (!pad) // protection against no pad in first cathode, which might happen
231 : {
232 : // try other cathode
233 144 : pad = GetNextPad(1);
234 144 : if (!pad)
235 : {
236 144 : return 0x0;
237 : }
238 : else
239 : {
240 0 : cluster = NewCluster();
241 : // Builds (recursively) a cluster on second cathode only
242 0 : AddPad(*cluster,pad);
243 : }
244 0 : }
245 : else
246 : {
247 : // Builds (recursively) a cluster on first cathode only
248 :
249 164 : cluster = NewCluster();
250 164 : AddPad(*cluster,pad);
251 :
252 164 : if ( !ShouldAbort() )
253 : {
254 : // On the 2nd cathode, only add pads overlapping with the current cluster
255 164 : TObjArray& padArray = *fPads[1];
256 164 : TIter next(&padArray);
257 : AliMUONPad* testPad;
258 :
259 1512 : while ( ( testPad = static_cast<AliMUONPad*>(next())) && !ShouldAbort() )
260 : {
261 510 : if (AreOverlapping(*testPad,*cluster) )
262 : {
263 164 : AddPad(*cluster,testPad);
264 : }
265 : }
266 164 : }
267 : }
268 :
269 164 : if ( ShouldAbort() )
270 : {
271 0 : AliCodeTimerAuto(Form("Skipping a precluster in DE %d because it got too many pads",fDetElemId),0);
272 0 : RemoveCluster(cluster);
273 0 : return NextCluster();
274 0 : }
275 :
276 164 : if ( cluster->Multiplicity() <= 1 )
277 : {
278 0 : if ( cluster->Multiplicity() == 0 )
279 : {
280 : // no pad is suspicious
281 0 : AliWarning("Got an empty cluster...");
282 0 : }
283 : // else only 1 pad (not suspicious, but kind of useless, probably noise)
284 : // so we remove it from our list
285 0 : RemoveCluster(cluster);
286 : // then proceed further
287 0 : return NextCluster();
288 : }
289 :
290 164 : return cluster;
291 308 : }
|