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 "AliMUONPreClusterFinderV2.h"
19 :
20 : #include "AliLog.h"
21 : #include "AliMUONCluster.h"
22 : #include "AliMpVSegmentation.h"
23 : #include "AliMpPad.h"
24 : #include "TObjArray.h"
25 : #include "TVector2.h"
26 : #include "AliMUONPad.h"
27 : #include "AliMUONVDigit.h"
28 : #include "AliMUONVDigitStore.h"
29 :
30 : //-----------------------------------------------------------------------------
31 : /// \class AliMUONPreClusterFinderV2
32 : ///
33 : /// Implementation of AliMUONVClusterFinder
34 : ///
35 : /// This one ressembles the preclustering stage in the original ClusterFinderAZ
36 : ///
37 : /// \author Laurent Aphecetche
38 : //-----------------------------------------------------------------------------
39 :
40 18 : ClassImp(AliMUONPreClusterFinderV2)
41 :
42 : //_____________________________________________________________________________
43 : AliMUONPreClusterFinderV2::AliMUONPreClusterFinderV2()
44 0 : : AliMUONVClusterFinder(),
45 0 : fClusters(0x0),
46 0 : fkSegmentations(0x0),
47 0 : fPads(0x0),
48 0 : fDetElemId(0)
49 0 : {
50 : /// ctor
51 0 : }
52 :
53 : //_____________________________________________________________________________
54 : AliMUONPreClusterFinderV2::~AliMUONPreClusterFinderV2()
55 0 : {
56 : /// dtor : note we're owner of the clusters, but not of the pads
57 0 : delete fClusters;
58 0 : }
59 :
60 : //_____________________________________________________________________________
61 : Bool_t
62 : AliMUONPreClusterFinderV2::UsePad(const AliMUONPad& pad)
63 : {
64 : /// Add a pad to the list of pads to be considered
65 0 : if ( pad.DetElemId() != fDetElemId )
66 : {
67 0 : AliError(Form("Cannot add pad from DE %d to this cluster finder which is "
68 : "currently dealing with DE %d",pad.DetElemId(),fDetElemId));
69 0 : return kFALSE;
70 : }
71 :
72 0 : fPads[pad.Cathode()]->Add(new AliMUONPad(pad));
73 : // FIXME: should set the ClusterId of that new pad to be -1
74 0 : return kTRUE;
75 0 : }
76 :
77 : //_____________________________________________________________________________
78 : Bool_t
79 : AliMUONPreClusterFinderV2::Prepare(Int_t detElemId,
80 : TObjArray* pads[2],
81 : const AliMpArea& area,
82 : const AliMpVSegmentation* seg[2])
83 : {
84 : /// Prepare for clustering, by giving access to segmentations and digit lists
85 :
86 0 : if ( area.IsValid() )
87 : {
88 0 : AliError("Handling of area not yet implemented for this class. Please check");
89 0 : }
90 :
91 0 : delete fClusters;
92 0 : fClusters = new TClonesArray("AliMUONCluster");
93 :
94 0 : fPads = pads;
95 0 : fkSegmentations = seg;
96 :
97 0 : fDetElemId = detElemId;
98 :
99 0 : if ( fPads[0]->GetLast() < 0 && fPads[1]->GetLast() < 0 )
100 : {
101 : // no pad at all, nothing to do...
102 0 : return kFALSE;
103 : }
104 :
105 0 : return kTRUE;
106 0 : }
107 :
108 : //_____________________________________________________________________________
109 : void
110 : AliMUONPreClusterFinderV2::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
111 : {
112 : /// Add a pad to a cluster
113 :
114 0 : AliMUONPad* addedPad = cluster.AddPad(*pad);
115 :
116 0 : Int_t cathode = pad->Cathode();
117 0 : TObjArray& padArray = *fPads[cathode];
118 0 : delete padArray.Remove(pad);
119 :
120 : // Check neighbours
121 0 : TObjArray neighbours;
122 0 : AliMpPad p = fkSegmentations[cathode]->PadByIndices(addedPad->Ix(),addedPad->Iy(),kTRUE);
123 0 : Int_t nn = fkSegmentations[cathode]->GetNeighbours(p,neighbours);
124 0 : for (Int_t in = 0; in < nn; ++in)
125 : {
126 0 : AliMpPad* p1 = static_cast<AliMpPad*>(neighbours.At(in));
127 :
128 0 : TIter next2(&padArray);
129 : AliMUONPad* p2;
130 :
131 0 : while ( ( p2 = static_cast<AliMUONPad*>(next2()) ) )
132 : {
133 0 : if ( !p2->IsUsed() && p2->Ix()==p1->GetIx()
134 0 : && p2->Iy() == p1->GetIy() &&
135 0 : p2->Cathode() == cathode )
136 : {
137 0 : AddPad(cluster,p2);
138 : }
139 : }
140 0 : } // for (Int_t in = 0;
141 0 : }
142 :
143 : namespace
144 : {
145 : //_____________________________________________________________________________
146 : Bool_t
147 : AreOverlapping(const AliMUONPad& pad, const AliMUONCluster& cluster)
148 : {
149 : /// Whether the pad overlaps with the cluster
150 :
151 : static Double_t precision = 1E-4; // cm
152 0 : static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
153 0 : for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
154 : {
155 0 : AliMUONPad* testPad = cluster.Pad(i);
156 : // Note: we use negative precision numbers, meaning
157 : // the area of the pads will be *increased* by these small numbers
158 : // prior to check the overlap by the AreOverlapping method,
159 : // so pads touching only by the corners will be considered as
160 : // overlapping.
161 0 : if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
162 : {
163 0 : return kTRUE;
164 : }
165 0 : }
166 0 : return kFALSE;
167 0 : }
168 : }
169 :
170 : //_____________________________________________________________________________
171 : AliMUONCluster*
172 : AliMUONPreClusterFinderV2::NextCluster()
173 : {
174 : /// Builds the next cluster, and returns it.
175 :
176 : // Start a new cluster
177 0 : Int_t id = fClusters->GetLast()+1;
178 0 : AliMUONCluster* cluster = new ((*fClusters)[id]) AliMUONCluster;
179 0 : cluster->SetUniqueID(id);
180 :
181 : AliMUONPad* pad;
182 0 : TIter next(fPads[0]);
183 0 : while ( ( pad = static_cast<AliMUONPad*>(next())) && pad->IsUsed() ) {}
184 :
185 0 : if (!pad) // protection against no pad in first cathode, which might happen
186 : {
187 : // try other cathode
188 0 : TIter next2(fPads[1]);
189 0 : while ( ( pad = static_cast<AliMUONPad*>(next2())) && pad->IsUsed() ) {}
190 0 : if (!pad)
191 : {
192 : // we are done.
193 0 : return 0x0;
194 : }
195 : // Builds (recursively) a cluster on second cathode only
196 0 : AddPad(*cluster,pad);
197 0 : }
198 : else
199 : {
200 : // Builds (recursively) a cluster on first cathode only
201 :
202 0 : AddPad(*cluster,pad);
203 :
204 : // On the 2nd cathode, only add pads overlapping with the current cluster
205 0 : TIter next1(fPads[1]);
206 : AliMUONPad* testPad;
207 :
208 0 : while ( ( testPad = static_cast<AliMUONPad*>(next1())))
209 : {
210 0 : if ( !testPad->IsUsed() && AreOverlapping(*testPad,*cluster) )
211 : {
212 0 : AddPad(*cluster,testPad);
213 : }
214 : }
215 0 : }
216 :
217 0 : if ( cluster->Multiplicity() <= 1 )
218 : {
219 0 : if ( cluster->Multiplicity() == 0 )
220 : {
221 : // no pad is suspicious
222 0 : AliWarning("Got an empty cluster...");
223 : }
224 : // else only 1 pad (not suspicious, but kind of useless, probably noise)
225 : // so we remove it from our list
226 0 : fClusters->Remove(cluster);
227 0 : fClusters->Compress();
228 : // then proceed further
229 0 : return NextCluster();
230 : }
231 :
232 0 : return cluster;
233 0 : }
|