3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
9 //* for The ALICE HLT Project. *
11 //* Permission to use, copy, modify and distribute this software and its *
12 //* documentation strictly for non-commercial purposes is hereby granted *
13 //* without fee, provided that the above copyright notice appears in all *
14 //* copies and that both the copyright notice and this permission notice *
15 //* appear in the supporting documentation. The authors make no claims *
16 //* about the suitability of this software for any purpose. It is *
17 //* provided "as is" without express or implied warranty. *
18 //**************************************************************************
20 // @file AliHLTTPCHWClusterMerger.cxx
21 // @author Matthias Richter, Sergey Gorbunov
23 // @brief Merger class for HLT TPC Hardware clusters
24 // Handles merging of branch border clusters
26 #include "AliHLTTPCHWClusterMerger.h"
27 #include "AliHLTTPCTransform.h"
28 #include "AliHLTTPCSpacePointData.h"
29 #include "AliHLTTPCHWCFSupport.h"
31 /** ROOT macro for the implementation of ROOT specific class methods */
32 ClassImp(AliHLTTPCHWClusterMerger)
34 AliHLTTPCHWClusterMerger::AliHLTTPCHWClusterMerger()
42 , fBorderFirstCluster(0)
44 , fBorderNClustersTotal(0)
46 , fRemovedClusterIds()
50 // see header file for class documentation
52 // refer to README to build package
54 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
58 AliHLTTPCHWClusterMerger::~AliHLTTPCHWClusterMerger()
63 delete[] fBorderNClusters;
64 delete[] fBorderFirstCluster;
65 delete[] fBorderClusters;
68 void AliHLTTPCHWClusterMerger::Init()
74 delete[] fBorderNClusters;
75 delete[] fBorderFirstCluster;
76 delete[] fBorderClusters;
80 fBorderFirstCluster = 0;
82 fBorderNClustersTotal = 0;
83 fNRows = AliHLTTPCTransform::GetNRows();
86 for( int i=0; i<fNRows; i++ ){
87 int nPads = AliHLTTPCTransform::GetNPads(i);
88 if( fNRowPads<nPads ) fNRowPads = nPads;
90 int nPadsTotal = fNRows*fNRowPads;
91 fMapping = new AliHLTInt16_t [nPadsTotal];
94 HLTError("Can not allocate memory: %d bytes", nPadsTotal*sizeof(AliHLTInt16_t));
97 for( int i=0; i<nPadsTotal; i++ ){
101 AliHLTTPCHWCFSupport support;
103 for( int iPart=0; iPart<6; iPart++ ){
104 const AliHLTUInt32_t *m = support.GetMapping(0,iPart);
106 for( int iHW=0; iHW<nHWAddress; iHW++ ){
107 AliHLTUInt32_t configWord = m[iHW+1];
108 int row = (configWord>>8) & 0x3F;
109 int pad = configWord & 0xFF;
110 bool border = (configWord>>14) & 0x1;
111 if( !border ) continue;
112 row+=AliHLTTPCTransform::GetFirstRow(iPart);
113 if( row>fNRows ) continue;
114 if( pad>=AliHLTTPCTransform::GetNPads(iPart) ) continue;
115 fMapping[row*fNRowPads + pad] = -2;
119 std::vector<AliHLTFloat32_t> vBorders;
120 for( int row=0; row<fNRows; row++ ){
121 for( int pad=0; pad<fNRowPads-1; pad++ ){
122 AliHLTInt16_t *m = fMapping + row*fNRowPads;
123 if( m[pad]==-2 && m[pad+1]==-2 ){
125 for( int i=1; i<fkMergeWidth; i++ ){
126 if( pad-i<0 || m[pad-i]!=-1 ) break;
127 m[pad-i] = fNBorders;
129 m[pad+1] = fNBorders+1;
130 for( int i=1; i<fkMergeWidth; i++ ){
131 if( pad+1+i>=fNRowPads || m[pad+1+i]!=-1 ) break;
132 m[pad+1+i] = fNBorders+1;
135 vBorders.push_back(pad+1.);
136 vBorders.push_back(pad+1.);
141 cout<<"Borders:"<<endl;
142 for( int row=0; row<fNRows; row++ ){
143 for( int pad=0; pad<fNRowPads; pad++ ){
144 AliHLTInt16_t *m = fMapping + row*fNRowPads;
146 cout<<row<<" "<<pad<<" "<<m[pad]%2<<endl;
151 fBorders = new AliHLTFloat32_t [fNBorders];
153 HLTError("Can not allocate memory: %d bytes", fNBorders*sizeof(AliHLTFloat32_t));
157 for( int i=0; i<fNBorders; i++ ){
158 fBorders[i] = vBorders[i];
160 fBorderNClusters = new int[fkNSlices*fNBorders];
161 if( !fBorderNClusters ){
162 HLTError("Can not allocate memory: %d bytes", fkNSlices*fNBorders*sizeof(int));
166 fBorderFirstCluster = new int[fkNSlices*fNBorders];
167 if( !fBorderFirstCluster ){
168 HLTError("Can not allocate memory: %d bytes", fkNSlices*fNBorders*sizeof(int));
172 for( int i=0; i<fkNSlices*fNBorders; i++){
173 fBorderNClusters[i] = 0;
174 fBorderFirstCluster[i] = 0;
178 bool AliHLTTPCHWClusterMerger::CheckCandidate(int /*slice*/, int partition, int partitionrow, float pad, float /*time*/, float sigmaPad2
181 /// check cluster if it is a candidate for merging
182 int slicerow=partitionrow+AliHLTTPCTransform::GetFirstRow(partition);
183 // cout<<"pad "<<pad<<" sigma2 "<<sigmaPad2<<endl;
185 if( !fMapping ) Init();
186 if( !fMapping ) return 0;
187 if( slicerow <0 || slicerow>= fNRows ) return 0;
188 int iPad = (int) pad;
189 if( iPad<0 || iPad>=fNRowPads ) return 0;
190 int atBorder = fMapping[partitionrow*fNRowPads+iPad];
191 if( atBorder<0 ) return 0;
192 float dPad = pad - fBorders[atBorder];
193 if( sigmaPad2>1.e-4 ){
194 if( dPad*dPad > 12.*sigmaPad2 ) return 0;
196 if( fabs(dPad)>1. ) return 0;
201 int AliHLTTPCHWClusterMerger::AddCandidate(int slice,
208 unsigned short charge,
213 /// add a candidate for merging and register in the index grid
216 int iPad = (int) pad;
217 if( !fMapping ) Init();
219 if (id!=~AliHLTUInt32_t(0)) {
221 slice=AliHLTTPCSpacePointData::GetSlice(id);
222 } else if ((unsigned)slice!=AliHLTTPCSpacePointData::GetSlice(id)) {
223 HLTError("cluster id 0x%08x is not consistent with specified slice %d", id, slice);
226 partition=AliHLTTPCSpacePointData::GetPatch(id);
227 } else if ((unsigned)partition!=AliHLTTPCSpacePointData::GetPatch(id)) {
228 HLTError("cluster id 0x%08x is not consistent with specified partition %d", id, partition);
231 if( slice<0 || slice>=fkNSlices ){
232 HLTError("cluster id 0x%08x has wrong slice number %d", id, slice);
234 if( partition<0 || partition>=6 ){
235 HLTError("cluster id 0x%08x has wrong partition number %d", id, partition);
238 if( slice>=0 && slice<fkNSlices && partition>=0 && partition<6 && fMapping && iPad>=0 && iPad < fNRowPads ){
239 iBorder = fMapping[partitionrow*fNRowPads+iPad];
241 float dPad = pad - fBorders[iBorder];
243 if( dPad*dPad > 12.*sigmaY2 ) iBorder = -1;
245 if( fabs(dPad)>1. ) iBorder = -1;
248 if( iBorder>=0 ) iBorder = slice*fkNSlices + iBorder;
251 fClusters.push_back(AliClusterRecord(slice, partition, iBorder, 0, id,
252 AliHLTTPCRawCluster(partitionrow, pad, time, sigmaY2, sigmaZ2, charge, qmax)));
255 fBorderNClusters[iBorder]++;
256 fBorderNClustersTotal++;
258 return fClusters.size();
261 int AliHLTTPCHWClusterMerger::FillIndex()
263 /// loop over cached raw clusters and fill index
265 delete[] fBorderClusters;
267 fBorderClusters = new AliBorderRecord[fBorderNClustersTotal];
269 fBorderFirstCluster[0] = 0;
270 for(int i=1; i<fkNSlices*fNBorders; i++ ){
271 fBorderFirstCluster[i] = fBorderFirstCluster[i-1] + fBorderNClusters[i-1];
272 fBorderNClusters[i-1] = 0;
274 fBorderNClusters[fkNSlices*fNBorders-1]=0;
275 for (AliHLTUInt32_t pos=0; pos<fClusters.size(); pos++) {
276 int iBorder = fClusters[pos].GetBorder();
277 if( iBorder<0 ) continue;
278 AliBorderRecord &b = fBorderClusters[fBorderFirstCluster[iBorder]+fBorderNClusters[iBorder]];
279 b.fClusterRecordID = pos;
280 b.fTimeBin = (int)fClusters[pos].GetCluster().GetTime();
281 fBorderNClusters[iBorder]++;
284 cout<<"Border clusters: "<<endl;
285 for( int iSlice=0; iSlice<fkNSlices; iSlice++){
286 for( int ib = 0; ib<fNBorders; ib++ ){
287 int ind = iSlice*fNBorders+ib;
288 cout<<iSlice<<" "<<ib<<" :"<<fBorderFirstCluster[ind]<<", "<<fBorderNClusters[ind]<<endl;
295 void AliHLTTPCHWClusterMerger::Clear()
299 fRemovedClusterIds.clear();
301 delete[] fBorderClusters;
303 for( int i=0; i<fkNSlices*fNBorders; i++){
304 fBorderNClusters[i] = 0;
305 fBorderFirstCluster[i] = 0;
307 fBorderNClustersTotal = 0;
311 int AliHLTTPCHWClusterMerger::Merge()
314 /// first all candidates are filled into the index grid, looping over all clusters
315 /// in the grid automatically results in time ordered clusters per row (ordering with
316 /// respect to cells, within a cell two clusters can be reversed)
318 if( !fMapping ) Init();
319 if( !fMapping ) return 0;
320 //static int sLeft = 0, sRight = 0, sMerged = 0;
323 if ((iResult=FillIndex())<0) {
327 for( int i=0; i<fkNSlices*fNBorders; i++){
328 std::sort(fBorderClusters+fBorderFirstCluster[i],fBorderClusters+fBorderFirstCluster[i]+fBorderNClusters[i], CompareTime);
331 for( int iBorder=0; iBorder<fkNSlices*fNBorders; iBorder+=2){
332 AliBorderRecord *border1 = fBorderClusters+fBorderFirstCluster[iBorder];
333 AliBorderRecord *border2 = fBorderClusters+fBorderFirstCluster[iBorder+1];
334 int n1 = fBorderNClusters[iBorder];
335 int n2 = fBorderNClusters[iBorder+1];
339 bool prn = (n1>0) && (n2>0);
341 cout<<"Border "<<iBorder/2<<", left: "<<n1<<" clusters :"<<endl;
342 for( int ib=0; ib<n1; ib++ ){
343 cout<<ib<<": "<<border1[ib].fTimeBin<<endl;
345 cout<<"Border "<<iBorder/2<<", right: "<<n2<<" clusters :"<<endl;
346 for( int ib=0; ib<n2; ib++ ){
347 cout<<ib<<": "<<border2[ib].fTimeBin<<endl;
352 for( int ib2 = 0; (ib1<n1) && (ib2<n2); ib2++ ){
353 // search first cluster at border1 to merge
355 while( ib1<n1 && border1[ib1].fTimeBin>border2[ib2].fTimeBin+fkMergeTimeWindow ){
359 if( ib1>= n1 ) break;
360 if( border1[ib1].fTimeBin < border2[ib2].fTimeBin-fkMergeTimeWindow) continue;
363 //if( prn ) cout<<"merge "<<ib2<<"->"<<ib1<<endl;
364 AliClusterRecord &c1 = fClusters[border1[ib1].fClusterRecordID];
365 AliClusterRecord &c2 = fClusters[border2[ib2].fClusterRecordID];
367 float w1 = c1.Cluster().fCharge;
368 float w2 = c2.Cluster().fCharge;
371 float w = 1./(w1+w2);
375 c1.Cluster().fCharge += c2.Cluster().fCharge;
376 c1.Cluster().fQMax += c2.Cluster().fQMax;
378 c1.Cluster().fSigmaY2 =
379 w1*c1.Cluster().fSigmaY2 + w2*c2.Cluster().fSigmaY2
380 + (c1.Cluster().fPad - c2.Cluster().fPad)*(c1.Cluster().fPad - c2.Cluster().fPad)*w1*w2;
382 c1.Cluster().fSigmaZ2 =
383 w1*c1.Cluster().fSigmaZ2 + w2*c2.Cluster().fSigmaZ2
384 + (c1.Cluster().fTime - c2.Cluster().fTime)*(c1.Cluster().fTime - c2.Cluster().fTime)*w1*w2;
386 c1.Cluster().fPad = w1*c1.Cluster().fPad + w2*c2.Cluster().fPad;
387 c1.Cluster().fTime = w1*c1.Cluster().fTime + w2*c2.Cluster().fTime;
391 fRemovedClusterIds.push_back(c2.GetId());
392 HLTDebug("merging %d into %d", border2[ib2].fClusterRecordID, border1[ib1].fClusterRecordID);
393 //cout<<"Set merged flag at position "<<border2[ib2].fClusterRecordID<<endl;
396 // do not merge c1 anymore
401 //cout<<"Merged "<<count<<" clusters "<<" out of "<<fClusters.size()<<endl;
403 // cout<<"L "<<sLeft<<" r "<<sRight<<" m "<<sMerged<<endl;
404 if (iResult<0) return iResult;