ALIROOT-5420 Changes for CDH v3
[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   AliMUONPad* addedPad = cluster.AddPad(*pad);
115   
116   Int_t cathode = pad->Cathode();
117   TObjArray& padArray = *fPads[cathode];
118   delete padArray.Remove(pad);
119   
120   // Check neighbours
121   TObjArray neighbours;
122   AliMpPad p = fkSegmentations[cathode]->PadByIndices(addedPad->Ix(),addedPad->Iy(),kTRUE);
123   Int_t nn = fkSegmentations[cathode]->GetNeighbours(p,neighbours);
124   for (Int_t in = 0; in < nn; ++in) 
125   {
126     AliMpPad* p1 = static_cast<AliMpPad*>(neighbours.At(in));
127     
128     TIter next2(&padArray);
129     AliMUONPad* p2;
130     
131     while ( ( p2 = static_cast<AliMUONPad*>(next2()) ) )
132     {
133         if ( !p2->IsUsed() && p2->Ix()==p1->GetIx() 
134              && p2->Iy() == p1->GetIy() &&
135              p2->Cathode() == cathode )
136         {
137           AddPad(cluster,p2);
138         }
139     }
140   } // for (Int_t in = 0;
141 }
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   static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
153   for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
154   {
155     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     if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
162     {
163       return kTRUE;
164     }
165   }
166   return kFALSE;
167 }
168 }
169
170 //_____________________________________________________________________________
171 AliMUONCluster* 
172 AliMUONPreClusterFinderV2::NextCluster()
173 {
174   /// Builds the next cluster, and returns it.
175   
176   // Start a new cluster
177   Int_t id = fClusters->GetLast()+1;
178   AliMUONCluster* cluster = new ((*fClusters)[id]) AliMUONCluster;
179   cluster->SetUniqueID(id);
180   
181   AliMUONPad* pad;
182   TIter next(fPads[0]);
183   while (  ( pad = static_cast<AliMUONPad*>(next())) && pad->IsUsed() ) {}
184
185   if (!pad) // protection against no pad in first cathode, which might happen
186   {
187     // try other cathode
188     TIter next2(fPads[1]);
189     while (  ( pad = static_cast<AliMUONPad*>(next2())) && pad->IsUsed() ) {}
190     if (!pad) 
191     {
192       // we are done.
193       return 0x0;
194     }
195     // Builds (recursively) a cluster on second cathode only
196     AddPad(*cluster,pad);
197   }
198   else
199   {
200     // Builds (recursively) a cluster on first cathode only
201       
202     AddPad(*cluster,pad);
203
204     // On the 2nd cathode, only add pads overlapping with the current cluster
205     TIter next1(fPads[1]);
206     AliMUONPad* testPad;
207   
208     while ( ( testPad = static_cast<AliMUONPad*>(next1())))
209     {
210       if ( !testPad->IsUsed() && AreOverlapping(*testPad,*cluster) )
211       {
212         AddPad(*cluster,testPad);
213       }
214     }
215   }
216   
217   if ( cluster->Multiplicity() <= 1 )
218   {
219     if ( cluster->Multiplicity() == 0 ) 
220     {
221       // no pad is suspicious
222       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     fClusters->Remove(cluster);
227     fClusters->Compress();
228     // then proceed further
229     return NextCluster();
230   }
231   
232   return cluster;
233 }