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