Replacing TClonesArray with TObjArray in cluster finder classes.
[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 "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 ClassImp(AliMUONPreClusterFinderV2)
41
42 //_____________________________________________________________________________
43 AliMUONPreClusterFinderV2::AliMUONPreClusterFinderV2()
44 : AliMUONVClusterFinder(),
45   fClusters(0x0),
46   fkSegmentations(0x0),
47   fPads(0x0),
48   fDetElemId(0)
49 {
50     /// ctor
51 }
52
53 //_____________________________________________________________________________
54 AliMUONPreClusterFinderV2::~AliMUONPreClusterFinderV2()
55 {
56   /// dtor : note we're owner of the clusters, but not of the pads
57   delete fClusters;
58 }
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   if ( pad.DetElemId() != fDetElemId )
66   {
67     AliError(Form("Cannot add pad from DE %d to this cluster finder which is "
68                   "currently dealing with DE %d",pad.DetElemId(),fDetElemId));
69     return kFALSE;
70   }
71   
72   fPads[pad.Cathode()]->Add(new AliMUONPad(pad)); 
73   // FIXME: should set the ClusterId of that new pad to be -1
74   return kTRUE;
75 }
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   if ( area.IsValid() ) 
87   {
88     AliError("Handling of area not yet implemented for this class. Please check");
89   }
90   
91   delete fClusters;
92   fClusters = new TClonesArray("AliMUONCluster");
93
94   fPads = pads;
95   fkSegmentations = seg;
96   
97   fDetElemId = detElemId;
98   
99   if ( fPads[0]->GetLast() < 0 && fPads[1]->GetLast() < 0 )
100   {
101     // no pad at all, nothing to do...
102     return kFALSE;
103   }
104
105   return kTRUE;
106 }
107
108 //_____________________________________________________________________________
109 void
110 AliMUONPreClusterFinderV2::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
111 {
112   /// Add a pad to a cluster
113   
114   cluster.AddPad(*pad);
115   pad->SetClusterId(cluster.GetUniqueID());
116   
117   Int_t cathode = pad->Cathode();
118   TObjArray& padArray = *fPads[cathode];
119   padArray.Remove(pad);
120   TIter next(&padArray);
121   
122   // Check neighbours
123   TObjArray neighbours;
124   AliMpPad p = fkSegmentations[pad->Cathode()]->PadByIndices(pad->Ix(),pad->Iy(),kTRUE);
125   Int_t nn = fkSegmentations[pad->Cathode()]->GetNeighbours(p,neighbours);
126   for (Int_t in = 0; in < nn; ++in) 
127   {
128     AliMpPad* p1 = static_cast<AliMpPad*>(neighbours.At(in));
129     
130     TIter next2(&padArray);
131     AliMUONPad* p2;
132     
133     while ( ( p2 = static_cast<AliMUONPad*>(next2()) ) )
134     {
135         if ( !p2->IsUsed() && p2->Ix()==p1->GetIx() 
136              && p2->Iy() == p1->GetIy() &&
137              p2->Cathode() == pad->Cathode() )
138         {
139           AddPad(cluster,p2);
140         }
141     }
142   } // for (Int_t in = 0;
143 }
144
145 namespace
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   static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
155   for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
156   {
157     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     if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
164     {
165       return kTRUE;
166     }
167   }
168   return kFALSE;
169 }
170 }
171
172 //_____________________________________________________________________________
173 AliMUONCluster* 
174 AliMUONPreClusterFinderV2::NextCluster()
175 {
176   /// Builds the next cluster, and returns it.
177   
178   // Start a new cluster
179   Int_t id = fClusters->GetLast()+1;
180   AliMUONCluster* cluster = new ((*fClusters)[id]) AliMUONCluster;
181   cluster->SetUniqueID(id);
182   
183   AliMUONPad* pad;
184   TIter next(fPads[0]);
185   while (  ( pad = static_cast<AliMUONPad*>(next())) && pad->IsUsed() ) {}
186
187   if (!pad) // protection against no pad in first cathode, which might happen
188   {
189     // try other cathode
190     TIter next2(fPads[1]);
191     while (  ( pad = static_cast<AliMUONPad*>(next2())) && pad->IsUsed() ) {}
192     if (!pad) 
193     {
194       // we are done.
195       return 0x0;
196     }
197     // Builds (recursively) a cluster on second cathode only
198     AddPad(*cluster,pad);
199   }
200   else
201   {
202     // Builds (recursively) a cluster on first cathode only
203       
204     AddPad(*cluster,pad);
205
206     // On the 2nd cathode, only add pads overlapping with the current cluster
207     TIter next1(fPads[1]);
208     AliMUONPad* testPad;
209   
210     while ( ( testPad = static_cast<AliMUONPad*>(next1())))
211     {
212       if ( !testPad->IsUsed() && AreOverlapping(*testPad,*cluster) )
213       {
214         AddPad(*cluster,testPad);
215       }
216     }
217   }
218   
219   if ( cluster->Multiplicity() <= 1 )
220   {
221     if ( cluster->Multiplicity() == 0 ) 
222     {
223       // no pad is suspicious
224       AliWarning("Got an empty cluster...");
225     }
226     // else only 1 pad (not suspicious, but kind of useless, probably noise)
227     // so we remove it from our list
228     fClusters->Remove(cluster);
229     fClusters->Compress();
230     // then proceed further
231     return NextCluster();
232   }
233   
234   return cluster;
235 }