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
28 #include "AliHLTTPCHWClusterMerger.h"
29 #include "AliHLTTPCTransform.h"
30 #include "AliHLTTPCSpacePointData.h"
31 #include "AliHLTTPCHWCFSupport.h"
33 /** ROOT macro for the implementation of ROOT specific class methods */
34 ClassImp(AliHLTTPCHWClusterMerger)
36 AliHLTTPCHWClusterMerger::AliHLTTPCHWClusterMerger()
44 , fBorderFirstCluster(0)
46 , fBorderNClustersTotal(0)
48 , fRemovedClusterIds()
52 // see header file for class documentation
54 // refer to README to build package
56 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
60 AliHLTTPCHWClusterMerger::~AliHLTTPCHWClusterMerger()
65 delete[] fBorderNClusters;
66 delete[] fBorderFirstCluster;
67 delete[] fBorderClusters;
70 void AliHLTTPCHWClusterMerger::Init()
76 delete[] fBorderNClusters;
77 delete[] fBorderFirstCluster;
78 delete[] fBorderClusters;
82 fBorderFirstCluster = 0;
84 fBorderNClustersTotal = 0;
85 fNRows = AliHLTTPCTransform::GetNRows();
88 for( int i=0; i<fNRows; i++ ){
89 int nPads = AliHLTTPCTransform::GetNPads(i);
90 if( fNRowPads<nPads ) fNRowPads = nPads;
92 int nPadsTotal = fNRows*fNRowPads;
93 fMapping = new AliHLTInt16_t [nPadsTotal];
96 HLTError("Can not allocate memory: %d bytes", nPadsTotal*sizeof(AliHLTInt16_t));
99 for( int i=0; i<nPadsTotal; i++ ){
103 AliHLTTPCHWCFSupport support;
105 for( int iPart=0; iPart<6; iPart++ ){
106 const AliHLTUInt32_t *m = support.GetMapping(0,iPart);
108 for( int iHW=0; iHW<nHWAddress; iHW++ ){
109 AliHLTUInt32_t configWord = m[iHW+1];
110 int row = (configWord>>8) & 0x3F;
111 int pad = configWord & 0xFF;
112 bool border = (configWord>>14) & 0x1;
113 if( !border ) continue;
114 row+=AliHLTTPCTransform::GetFirstRow(iPart);
115 if( row>fNRows ) continue;
116 if( pad>=AliHLTTPCTransform::GetNPads(iPart) ) continue;
117 fMapping[row*fNRowPads + pad] = -2;
121 std::vector<AliHLTFloat32_t> vBorders;
122 for( int row=0; row<fNRows; row++ ){
123 for( int pad=0; pad<fNRowPads-1; pad++ ){
124 AliHLTInt16_t *m = fMapping + row*fNRowPads;
125 if( m[pad]==-2 && m[pad+1]==-2 ){
127 for( int i=1; i<fkMergeWidth; i++ ){
128 if( pad-i<0 || m[pad-i]!=-1 ) break;
129 m[pad-i] = fNBorders;
131 m[pad+1] = fNBorders+1;
132 for( int i=1; i<fkMergeWidth; i++ ){
133 if( pad+1+i>=fNRowPads || m[pad+1+i]!=-1 ) break;
134 m[pad+1+i] = fNBorders+1;
137 vBorders.push_back(pad+1.);
138 vBorders.push_back(pad+1.);
143 cout<<"Borders:"<<endl;
144 for( int row=0; row<fNRows; row++ ){
145 for( int pad=0; pad<fNRowPads; pad++ ){
146 AliHLTInt16_t *m = fMapping + row*fNRowPads;
148 cout<<row<<" "<<pad<<" "<<m[pad]%2<<endl;
153 fBorders = new AliHLTFloat32_t [fNBorders];
155 HLTError("Can not allocate memory: %d bytes", fNBorders*sizeof(AliHLTFloat32_t));
159 for( int i=0; i<fNBorders; i++ ){
160 fBorders[i] = vBorders[i];
162 fBorderNClusters = new int[fkNSlices*fNBorders];
163 if( !fBorderNClusters ){
164 HLTError("Can not allocate memory: %d bytes", fkNSlices*fNBorders*sizeof(int));
168 fBorderFirstCluster = new int[fkNSlices*fNBorders];
169 if( !fBorderFirstCluster ){
170 HLTError("Can not allocate memory: %d bytes", fkNSlices*fNBorders*sizeof(int));
174 for( int i=0; i<fkNSlices*fNBorders; i++){
175 fBorderNClusters[i] = 0;
176 fBorderFirstCluster[i] = 0;
180 bool AliHLTTPCHWClusterMerger::CheckCandidate(int /*slice*/, int partition, int partitionrow, float pad, float /*time*/, float sigmaPad2
183 /// check cluster if it is a candidate for merging
184 int slicerow=partitionrow+AliHLTTPCTransform::GetFirstRow(partition);
185 // cout<<"pad "<<pad<<" sigma2 "<<sigmaPad2<<endl;
187 if( !fMapping ) Init();
188 if( !fMapping ) return 0;
189 if( slicerow <0 || slicerow>= fNRows ) return 0;
190 int iPad = (int) pad;
191 if( iPad<0 || iPad>=fNRowPads ) return 0;
192 int atBorder = fMapping[partitionrow*fNRowPads+iPad];
193 if( atBorder<0 ) return 0;
194 float dPad = pad - fBorders[atBorder];
195 if( sigmaPad2>1.e-4 ){
196 if( dPad*dPad > 12.*sigmaPad2 ) return 0;
198 if( fabs(dPad)>1. ) return 0;
203 int AliHLTTPCHWClusterMerger::AddCandidate(int slice,
210 unsigned short charge,
213 const AliHLTTPCClusterMCLabel &mc
216 /// add a candidate for merging and register in the index grid
219 int iPad = (int) pad;
220 if( !fMapping ) Init();
222 if (id!=~AliHLTUInt32_t(0)) {
224 slice=AliHLTTPCSpacePointData::GetSlice(id);
225 } else if ((unsigned)slice!=AliHLTTPCSpacePointData::GetSlice(id)) {
226 HLTError("cluster id 0x%08x is not consistent with specified slice %d", id, slice);
229 partition=AliHLTTPCSpacePointData::GetPatch(id);
230 } else if ((unsigned)partition!=AliHLTTPCSpacePointData::GetPatch(id)) {
231 HLTError("cluster id 0x%08x is not consistent with specified partition %d", id, partition);
234 if( slice<0 || slice>=fkNSlices ){
235 HLTError("cluster id 0x%08x has wrong slice number %d", id, slice);
237 if( partition<0 || partition>=6 ){
238 HLTError("cluster id 0x%08x has wrong partition number %d", id, partition);
241 if( slice>=0 && slice<fkNSlices && partition>=0 && partition<6 && fMapping && iPad>=0 && iPad < fNRowPads ){
242 iBorder = fMapping[partitionrow*fNRowPads+iPad];
244 float dPad = pad - fBorders[iBorder];
246 if( dPad*dPad > 12.*sigmaY2 ) iBorder = -1;
248 if( fabs(dPad)>1. ) iBorder = -1;
251 if( iBorder>=0 ) iBorder = slice*fkNSlices + iBorder;
254 fClusters.push_back(AliClusterRecord(slice, partition, iBorder, 0, id,
255 AliHLTTPCRawCluster(partitionrow, pad, time, sigmaY2, sigmaZ2, charge, qmax), mc ));
258 fBorderNClusters[iBorder]++;
259 fBorderNClustersTotal++;
261 return fClusters.size();
264 int AliHLTTPCHWClusterMerger::FillIndex()
266 /// loop over cached raw clusters and fill index
268 delete[] fBorderClusters;
270 fBorderClusters = new AliBorderRecord[fBorderNClustersTotal];
272 fBorderFirstCluster[0] = 0;
273 for(int i=1; i<fkNSlices*fNBorders; i++ ){
274 fBorderFirstCluster[i] = fBorderFirstCluster[i-1] + fBorderNClusters[i-1];
275 fBorderNClusters[i-1] = 0;
277 fBorderNClusters[fkNSlices*fNBorders-1]=0;
278 for (AliHLTUInt32_t pos=0; pos<fClusters.size(); pos++) {
279 int iBorder = fClusters[pos].GetBorder();
280 if( iBorder<0 ) continue;
281 AliBorderRecord &b = fBorderClusters[fBorderFirstCluster[iBorder]+fBorderNClusters[iBorder]];
282 b.fClusterRecordID = pos;
283 b.fTimeBin = (int)fClusters[pos].GetCluster().GetTime();
284 fBorderNClusters[iBorder]++;
287 cout<<"Border clusters: "<<endl;
288 for( int iSlice=0; iSlice<fkNSlices; iSlice++){
289 for( int ib = 0; ib<fNBorders; ib++ ){
290 int ind = iSlice*fNBorders+ib;
291 cout<<iSlice<<" "<<ib<<" :"<<fBorderFirstCluster[ind]<<", "<<fBorderNClusters[ind]<<endl;
298 void AliHLTTPCHWClusterMerger::Clear()
302 fRemovedClusterIds.clear();
304 delete[] fBorderClusters;
306 for( int i=0; i<fkNSlices*fNBorders; i++){
307 fBorderNClusters[i] = 0;
308 fBorderFirstCluster[i] = 0;
310 fBorderNClustersTotal = 0;
314 int AliHLTTPCHWClusterMerger::Merge()
317 /// first all candidates are filled into the index grid, looping over all clusters
318 /// in the grid automatically results in time ordered clusters per row (ordering with
319 /// respect to cells, within a cell two clusters can be reversed)
321 if( !fMapping ) Init();
322 if( !fMapping ) return 0;
323 //static int sLeft = 0, sRight = 0, sMerged = 0;
326 if ((iResult=FillIndex())<0) {
330 for( int i=0; i<fkNSlices*fNBorders; i++){
331 std::sort(fBorderClusters+fBorderFirstCluster[i],fBorderClusters+fBorderFirstCluster[i]+fBorderNClusters[i], CompareTime);
334 for( int iBorder=0; iBorder<fkNSlices*fNBorders; iBorder+=2){
335 AliBorderRecord *border1 = fBorderClusters+fBorderFirstCluster[iBorder];
336 AliBorderRecord *border2 = fBorderClusters+fBorderFirstCluster[iBorder+1];
337 int n1 = fBorderNClusters[iBorder];
338 int n2 = fBorderNClusters[iBorder+1];
342 bool prn = (n1>0) && (n2>0);
344 cout<<"Border "<<iBorder/2<<", left: "<<n1<<" clusters :"<<endl;
345 for( int ib=0; ib<n1; ib++ ){
346 cout<<ib<<": "<<border1[ib].fTimeBin<<endl;
348 cout<<"Border "<<iBorder/2<<", right: "<<n2<<" clusters :"<<endl;
349 for( int ib=0; ib<n2; ib++ ){
350 cout<<ib<<": "<<border2[ib].fTimeBin<<endl;
355 for( int ib2 = 0; (ib1<n1) && (ib2<n2); ib2++ ){
356 // search first cluster at border1 to merge
358 while( ib1<n1 && border1[ib1].fTimeBin>border2[ib2].fTimeBin+fkMergeTimeWindow ){
362 if( ib1>= n1 ) break;
363 if( border1[ib1].fTimeBin < border2[ib2].fTimeBin-fkMergeTimeWindow) continue;
366 //if( prn ) cout<<"merge "<<ib2<<"->"<<ib1<<endl;
367 AliClusterRecord &c1 = fClusters[border1[ib1].fClusterRecordID];
368 AliClusterRecord &c2 = fClusters[border2[ib2].fClusterRecordID];
370 float w1 = c1.Cluster().fCharge;
371 float w2 = c2.Cluster().fCharge;
374 float w = 1./(w1+w2);
378 c1.Cluster().fCharge += c2.Cluster().fCharge;
379 c1.Cluster().fQMax += c2.Cluster().fQMax;
381 c1.Cluster().fSigmaY2 =
382 w1*c1.Cluster().fSigmaY2 + w2*c2.Cluster().fSigmaY2
383 + (c1.Cluster().fPad - c2.Cluster().fPad)*(c1.Cluster().fPad - c2.Cluster().fPad)*w1*w2;
385 c1.Cluster().fSigmaZ2 =
386 w1*c1.Cluster().fSigmaZ2 + w2*c2.Cluster().fSigmaZ2
387 + (c1.Cluster().fTime - c2.Cluster().fTime)*(c1.Cluster().fTime - c2.Cluster().fTime)*w1*w2;
389 c1.Cluster().fPad = w1*c1.Cluster().fPad + w2*c2.Cluster().fPad;
390 c1.Cluster().fTime = w1*c1.Cluster().fTime + w2*c2.Cluster().fTime;
394 AliHLTTPCClusterMCWeight labels[6] = {
395 c1.GetMCLabel().fClusterID[0],
396 c1.GetMCLabel().fClusterID[1],
397 c1.GetMCLabel().fClusterID[2],
398 c2.GetMCLabel().fClusterID[0],
399 c2.GetMCLabel().fClusterID[1],
400 c2.GetMCLabel().fClusterID[2]
403 sort(labels, labels+6, CompareMCLabels);
404 for( unsigned int i=1; i<6; i++ ){
405 if(labels[i-1].fMCID==labels[i].fMCID ){
406 labels[i].fWeight+=labels[i-1].fWeight;
407 labels[i-1].fWeight = 0;
411 sort(labels, labels+6, CompareMCWeights );
413 for( unsigned int i=0; i<3 && i<6; i++ ){
414 c1.MCLabel().fClusterID[i] = labels[i];
418 fRemovedClusterIds.push_back(c2.GetId());
419 HLTDebug("merging %d into %d", border2[ib2].fClusterRecordID, border1[ib1].fClusterRecordID);
420 //cout<<"Set merged flag at position "<<border2[ib2].fClusterRecordID<<endl;
423 // do not merge c1 anymore
428 //cout<<"Merged "<<count<<" clusters "<<" out of "<<fClusters.size()<<endl;
430 // cout<<"L "<<sLeft<<" r "<<sRight<<" m "<<sMerged<<endl;
431 if (iResult<0) return iResult;