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