]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/TPCLib/AliHLTTPCClustFinderNew.cxx
- made package indepentend of src
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCClustFinderNew.cxx
CommitLineData
a6c02c85 1// @(#) $Id$
2
3// Author: Anders Vestbo <mailto:vestbo@fi.uib.no>, Constantin Loizides <mailto:loizides@ikf.uni-frankfurt.de>
4//*-- Copyright &copy ALICE HLT Group
5
a6c02c85 6#include "AliHLTTPCRootTypes.h"
7#include "AliHLTTPCLogging.h"
8#include "AliHLTTPCClustFinderNew.h"
9#include "AliHLTTPCDigitData.h"
10#include "AliHLTTPCTransform.h"
11#include "AliHLTTPCSpacePointData.h"
12#include "AliHLTTPCMemHandler.h"
13
14#if __GNUC__ >= 3
15using namespace std;
16#endif
17
18/** \class AliHLTTPCClustFinderNew
19<pre>
20//_____________________________________________________________
21// AliHLTTPCClustFinderNew
22//
23// The current cluster finder for HLT
24// (Based on STAR L3)
25//
26// The cluster finder is initialized with the Init function,
27// providing the slice and patch information to work on.
28// The input is a AliHLTTPCDigitRowData structure using the
29// Read function. The resulting space points will be in the
30// array given by the SetOutputArray function.
31//
32// There are several setters which control the behaviour:
33//
34// - SetXYError(Float_t): set fixed error in XY direction
35// - SetZError(Float_t): set fixed error in Z direction
36// (used if errors are not calculated)
37// - SetDeconv(Bool_t): switch on/off deconvolution
38// - SetThreshold(UInt_t): set charge threshold for cluster
39// - SetMatchWidth(UInt_t): set the match distance in
40// time for sequences to be merged
41// - SetSTDOutput(Bool_t): switch on/off output about found clusters
42// - SetCalcErr(Bool_t): switch on/off calculation of
43// space point errors (or widths in raw system)
44// - SetRawSP(Bool_t): switch on/off convertion to raw system
45//
46//
47// Example Usage:
48//
49// AliHLTTPCFileHandler *file = new AliHLTTPCFileHandler();
50// file->SetAliInput(digitfile); //give some input file
51// for(int slice=0; slice<=35; slice++){
52// for(int patch=0; pat<6; pat++){
53// file->Init(slice,patch);
54// UInt_t ndigits=0;
55// UInt_t maxclusters=100000;
56// UInt_t pointsize = maxclusters*sizeof(AliHLTTPCSpacePointData);
57// AliHLTTPCSpacePointData *points = (AliHLTTPCSpacePointData*)memory->Allocate(pointsize);
58// AliHLTTPCDigitRowData *digits = (AliHLTTPCDigitRowData*)file->AliAltroDigits2Memory(ndigits,event);
59// AliHLTTPCClustFinderNew *cf = new AliHLTTPCClustFinderNew();
60// cf->SetMatchWidth(2);
61// cf->InitSlice(slice,patch,maxclusters);
62// cf->SetSTDOutput(kTRUE); //Some output to standard IO
63// cf->SetRawSP(kFALSE); //Convert space points to local system
64// cf->SetThreshold(5); //Threshold of cluster charge
65// cf->SetDeconv(kTRUE); //Deconv in pad and time direction
66// cf->SetCalcErr(kTRUE); //Calculate the errors of the spacepoints
67// cf->SetOutputArray(points); //Move the spacepoints to the array
68// cf->Read(ndigits,digits); //give the data to the cf
69// cf->ProcessDigits(); //process the rows given by init
70// Int_t npoints = cf->GetNumberOfClusters();
71// AliHLTTPCMemHandler *out= new AliHLTTPCMemHandler();
72// out->SetBinaryOutput(fname);
73// out->Memory2Binary(npoints,points); //store the spacepoints
74// out->CloseBinaryOutput();
75// delete out;
76// file->free();
77// delete cf;
78// }
79// }
80</pre>
81*/
82
83ClassImp(AliHLTTPCClustFinderNew)
84
85AliHLTTPCClustFinderNew::AliHLTTPCClustFinderNew()
86{
87 //constructor
88 fMatch = 1;
89 fThreshold = 10;
90 fXYErr = 0.2;
91 fZErr = 0.3;
92 fDeconvPad = kTRUE;
93 fDeconvTime = kTRUE;
94 fStdout = kFALSE;
95 fCalcerr = kTRUE;
96 fRawSP = kFALSE;
97 fFirstRow=0;
98 fLastRow=0;
99}
100
101AliHLTTPCClustFinderNew::~AliHLTTPCClustFinderNew()
102{
103 //destructor
104 ;
105}
106
107void AliHLTTPCClustFinderNew::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
108{
109 //init slice
110 fNClusters = 0;
111 fMaxNClusters = nmaxpoints;
112 fCurrentSlice = slice;
113 fCurrentPatch = patch;
114 fFirstRow = firstrow;
115 fLastRow = lastrow;
116}
117
118void AliHLTTPCClustFinderNew::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
119{
120 //init slice
121 fNClusters = 0;
122 fMaxNClusters = nmaxpoints;
123 fCurrentSlice = slice;
124 fCurrentPatch = patch;
125 fFirstRow=AliHLTTPCTransform::GetFirstRow(patch);
126 fLastRow=AliHLTTPCTransform::GetLastRow(patch);
127}
128
129void AliHLTTPCClustFinderNew::SetOutputArray(AliHLTTPCSpacePointData *pt)
130{
131 //set pointer to output
132 fSpacePointData = pt;
133}
134
135void AliHLTTPCClustFinderNew::Read(UInt_t ndigits,AliHLTTPCDigitRowData *ptr)
136{
137 //set input pointer
138 fNDigitRowData = ndigits;
139 fDigitRowData = ptr;
140}
141
142void AliHLTTPCClustFinderNew::ProcessDigits()
143{
144 //Loop over rows, and call processrow
145 AliHLTTPCDigitRowData *tempPt = (AliHLTTPCDigitRowData*)fDigitRowData;
146 fNClusters = 0;
147 for(Int_t i=fFirstRow; i<=fLastRow; i++)
148 {
149 fCurrentRow = i;
150 if((Int_t)tempPt->fRow!=fCurrentRow){
151 LOG(AliHLTTPCLog::kWarning,"AliHLTTPCClustFinderNew::ProcessDigits","Digits")
152 <<"Row number should match! "<<tempPt->fRow<<" "<<fCurrentRow<<ENDLOG;
153 continue;
154 }
155 ProcessRow(tempPt);
156 Byte_t *tmp = (Byte_t*)tempPt;
157 Int_t size = sizeof(AliHLTTPCDigitRowData) + tempPt->fNDigit*sizeof(AliHLTTPCDigitData);
158 tmp += size;
159 tempPt = (AliHLTTPCDigitRowData*)tmp;
160 }
161 LOG(AliHLTTPCLog::kInformational,"AliHLTTPCClustFinderNew::ProcessDigits","Space points")
162 <<"Cluster finder found "<<fNClusters<<" clusters in slice "<<fCurrentSlice
163 <<" patch "<<fCurrentPatch<<ENDLOG;
164}
165
166void AliHLTTPCClustFinderNew::ProcessRow(AliHLTTPCDigitRowData *tempPt)
167{
168 //process row
169 UInt_t lastpad = 123456789;
170
171 AliClusterData *pad1[5000]; //2 lists for internal memory=2pads
172 AliClusterData *pad2[5000]; //2 lists for internal memory=2pads
173 AliClusterData clusterlist[10000]; //Clusterlist
174
175 AliClusterData **currentPt; //List of pointers to the current pad
176 AliClusterData **previousPt; //List of pointers to the previous pad
177 currentPt = pad2;
178 previousPt = pad1;
179 UInt_t nprevious=0,ncurrent=0,ntotal=0;
180
181 //Loop over sequences of this row:
182 for(UInt_t bin=0; bin<tempPt->fNDigit; bin++)
183 {
184 AliHLTTPCDigitData *data = tempPt->fDigitData;
185 if(data[bin].fPad != lastpad)
186 {
187 //This is a new pad
188
189 //Switch the lists:
190 if(currentPt == pad2)
191 {
192 currentPt = pad1;
193 previousPt = pad2;
194 }
195 else
196 {
197 currentPt = pad2;
198 previousPt = pad1;
199 }
200 nprevious = ncurrent;
201 ncurrent = 0;
202 if(bin[data].fPad != lastpad+1)
203 {
204 //this happens if there is a pad with no signal.
205 nprevious = ncurrent = 0;
206 }
207 lastpad = data[bin].fPad;
208 }
209
210 Bool_t newcluster = kTRUE;
211 UInt_t seqcharge=0,seqaverage=0,seqerror=0;
212 UInt_t lastcharge=0,lastwas_falling=0;
213 Int_t newbin=-1;
214
215 if(fDeconvTime)
216 {
217 redo: //This is a goto.
218 if(newbin > -1)
219 {
220 bin = newbin;
221 newbin = -1;
222 }
223
224 lastcharge=0;
225 lastwas_falling = 0;
226 }
227
228 while(1) //Loop over current sequence
229 {
230 if(data[bin].fTime >= AliHLTTPCTransform::GetNTimeBins())
231 {
232 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClustFinderNew::ProcessRow","Digits")
233 <<"Timebin out of range "<<(Int_t)data[bin].fTime<<ENDLOG;
234 break;
235 }
236
237 //Get the current ADC-value
238 UInt_t charge = data[bin].fCharge;
239
240 if(fDeconvTime)
241 {
242 //Check if the last pixel in the sequence is smaller than this
243 if(charge > lastcharge)
244 {
245 if(lastwas_falling)
246 {
247 newbin = bin;
248 break;
249 }
250 }
251 else lastwas_falling = 1; //last pixel was larger than this
252 lastcharge = charge;
253 }
254
255 //Sum the total charge of this sequence
256 seqcharge += charge;
257 seqaverage += data[bin].fTime*charge;
258 seqerror += data[bin].fTime*data[bin].fTime*charge;
259
260 //Check where to stop:
261 if(bin >= tempPt->fNDigit - 1) //out of range
262 break;
263 if(data[bin+1].fPad != data[bin].fPad) //new pad
264 break;
265 if(data[bin+1].fTime != data[bin].fTime+1) //end of sequence
266 break;
267
268 bin++;
269 }//end loop over sequence
270
271 //Calculate mean of sequence:
272 Int_t seqmean=0;
273 if(seqcharge)
274 seqmean = seqaverage/seqcharge;
275 else
276 {
277 LOG(AliHLTTPCLog::kFatal,"AliHLTTPCClustFinderNew::ProcessRow","Data")
278 <<"Error in data given to the cluster finder"<<ENDLOG;
279 seqmean = 1;
280 seqcharge = 1;
281 }
282
283 //Calculate mean in pad direction:
284 Int_t padmean = seqcharge*data[bin].fPad;
285 Int_t paderror = data[bin].fPad*padmean;
286
287 //Compare with results on previous pad:
288 for(UInt_t p=0; p<nprevious; p++)
289 {
290 //dont merge sequences on the same pad twice
291 if(previousPt[p]->fLastMergedPad==data[bin].fPad) continue;
292
293 Int_t difference = seqmean - previousPt[p]->fMean;
294 if(difference < -fMatch) break;
295
296 if(difference <= fMatch) //There is a match here!!
297 {
298 AliClusterData *local = previousPt[p];
299
300 if(fDeconvPad)
301 {
302 if(seqcharge > local->fLastCharge)
303 {
304 if(local->fChargeFalling) //The previous pad was falling
305 {
306 break; //create a new cluster
307 }
308 }
309 else
310 local->fChargeFalling = 1;
311 local->fLastCharge = seqcharge;
312 }
313
314 //Don't create a new cluster, because we found a match
315 newcluster = kFALSE;
316
317 //Update cluster on current pad with the matching one:
318 local->fTotalCharge += seqcharge;
319 local->fPad += padmean;
320 local->fPad2 += paderror;
321 local->fTime += seqaverage;
322 local->fTime2 += seqerror;
323 local->fMean = seqmean;
324 local->fFlags++; //means we have more than one pad
325 local->fLastMergedPad = data[bin].fPad;
326
327 currentPt[ncurrent] = local;
328 ncurrent++;
329
330 break;
331 } //Checking for match at previous pad
332 } //Loop over results on previous pad.
333
334 if(newcluster)
335 {
336 //Start a new cluster. Add it to the clusterlist, and update
337 //the list of pointers to clusters in current pad.
338 //current pad will be previous pad on next pad.
339
340 //Add to the clusterlist:
341 AliClusterData *tmp = &clusterlist[ntotal];
342 tmp->fTotalCharge = seqcharge;
343 tmp->fPad = padmean;
344 tmp->fPad2 = paderror;
345 tmp->fTime = seqaverage;
346 tmp->fTime2 = seqerror;
347 tmp->fMean = seqmean;
348 tmp->fFlags = 0; //flags for single pad clusters
349 tmp->fLastMergedPad = data[bin].fPad;
350
351 if(fDeconvPad)
352 {
353 tmp->fChargeFalling = 0;
354 tmp->fLastCharge = seqcharge;
355 }
356
357 //Update list of pointers to previous pad:
358 currentPt[ncurrent] = &clusterlist[ntotal];
359 ntotal++;
360 ncurrent++;
361 }
362
363 if(fDeconvTime)
364 if(newbin >= 0) goto redo;
365 }//Loop over digits on this padrow
366
367 WriteClusters(ntotal,clusterlist);
368}
369
370void AliHLTTPCClustFinderNew::WriteClusters(Int_t nclusters,AliClusterData *list)
371{
372 //write cluster to output pointer
373 Int_t thisrow,thissector;
374 UInt_t counter = fNClusters;
375
376 for(int j=0; j<nclusters; j++)
377 {
378 if(!list[j].fFlags) continue; //discard single pad clusters
379 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
380
381 Float_t xyz[3];
382 Float_t fpad =(Float_t)list[j].fPad / list[j].fTotalCharge;
383 Float_t fpad2=fXYErr*fXYErr; //fixed given error
384 Float_t ftime =(Float_t)list[j].fTime / list[j].fTotalCharge;
385 Float_t ftime2=fZErr*fZErr; //fixed given error
386
387 if(fCalcerr) { //calc the errors, otherwice take the fixed error
388 Int_t patch = AliHLTTPCTransform::GetPatch(fCurrentRow);
389 UInt_t q2=list[j].fTotalCharge*list[j].fTotalCharge;
390 Float_t sy2=list[j].fPad2 * list[j].fTotalCharge - list[j].fPad * list[j].fPad;
391 sy2/=q2;
392 if(sy2 < 0) {
393 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinderNew::WriteClusters","Cluster width")
394 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
395 continue;
396 } else {
397 if(!fRawSP){
398 fpad2 = (sy2 + 1./12)*AliHLTTPCTransform::GetPadPitchWidth(patch)*AliHLTTPCTransform::GetPadPitchWidth(patch);
399 if(sy2 != 0){
400 fpad2*=0.108; //constants are from offline studies
401 if(patch<2)
402 fpad2*=2.07;
403 }
404 } else fpad2=sy2; //take the width not the error
405 }
406 Float_t sz2=list[j].fTime2*list[j].fTotalCharge - list[j].fTime*list[j].fTime;
407 sz2/=q2;
408 if(sz2 < 0){
409 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinderNew::WriteClusters","Cluster width")
410 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
411 continue;
412 } else {
413 if(!fRawSP){
414 ftime2 = (sz2 + 1./12)*AliHLTTPCTransform::GetZWidth()*AliHLTTPCTransform::GetZWidth();
415 if(sz2 != 0) {
416 ftime2 *= 0.169; //constants are from offline studies
417 if(patch<2)
418 ftime2 *= 1.77;
419 }
420 } else ftime2=sz2; //take the width, not the error
421 }
422 }
423 if(fStdout==kTRUE)
424 cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
425
426 if(!fRawSP){
427 AliHLTTPCTransform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
428 AliHLTTPCTransform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
429
430 if(xyz[0]==0) LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder","Cluster Finder")
431 <<AliHLTTPCLog::kDec<<"Zero cluster"<<ENDLOG;
432 if(fNClusters >= fMaxNClusters)
433 {
434 LOG(AliHLTTPCLog::kError,"AliHLTTPCClustFinder::WriteClusters","Cluster Finder")
435 <<AliHLTTPCLog::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
436 return;
437 }
438
439 fSpacePointData[counter].fX = xyz[0];
440 fSpacePointData[counter].fY = xyz[1];
441 fSpacePointData[counter].fZ = xyz[2];
442
443 } else {
444 fSpacePointData[counter].fX = fCurrentRow;
445 fSpacePointData[counter].fY = fpad;
446 fSpacePointData[counter].fZ = ftime;
447 }
448
449 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
450 fSpacePointData[counter].fPadRow = fCurrentRow;
451 fSpacePointData[counter].fSigmaY2 = fpad2;
452 fSpacePointData[counter].fSigmaZ2 = ftime2;
453
454 Int_t patch=fCurrentPatch;
455 if(patch==-1) patch=0; //never store negative patch number
456 fSpacePointData[counter].fID = counter
457 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
458#ifdef do_mc
459 Int_t trackID[3];
460 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
461
462 fSpacePointData[counter].fTrackID[0] = trackID[0];
463 fSpacePointData[counter].fTrackID[1] = trackID[1];
464 fSpacePointData[counter].fTrackID[2] = trackID[2];
465
466 //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;
467#endif
468
469 fNClusters++;
470 counter++;
471 }
472}
473
474#ifdef do_mc
475void AliHLTTPCClustFinderNew::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
476{
477 //get mc id
478 AliHLTTPCDigitRowData *rowPt = (AliHLTTPCDigitRowData*)fDigitRowData;
479
480 trackID[0]=trackID[1]=trackID[2]=-2;
481 //cout<<"Looking for pad "<<pad<<" time "<<time<<endl;
482 for(Int_t i=fFirstRow; i<=fLastRow; i++){
483 if(rowPt->fRow < (UInt_t)fCurrentRow){
484 AliHLTTPCMemHandler::UpdateRowPointer(rowPt);
485 continue;
486 }
487 AliHLTTPCDigitData *digPt = (AliHLTTPCDigitData*)rowPt->fDigitData;
488 for(UInt_t j=0; j<rowPt->fNDigit; j++){
489 Int_t cpad = digPt[j].fPad;
490 Int_t ctime = digPt[j].fTime;
491 if(cpad != pad) continue;
492 if(ctime != time) continue;
493
494 trackID[0] = digPt[j].fTrackID[0];
495 trackID[1] = digPt[j].fTrackID[1];
496 trackID[2] = digPt[j].fTrackID[2];
497
498 //cout<<"Reading row "<<fCurrentRow<<" pad "<<cpad<<" time "<<ctime<<" trackID "<<digPt[j].fTrackID[0]<<endl;
499 break;
500 }
501 break;
502 }
503}
504#endif