3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>, Constantin Loizides <mailto:loizides@ikf.uni-frankfurt.de>
4 //*-- Copyright © ALICE HLT Group
6 #include "AliL3StandardIncludes.h"
8 #include "AliL3Logging.h"
9 #include "AliL3ClustFinderNew.h"
10 #include "AliL3DigitData.h"
11 #include "AliL3Transform.h"
12 #include "AliL3SpacePointData.h"
13 #include "AliL3MemHandler.h"
19 /** \class AliL3ClustFinderNew
21 //_____________________________________________________________
22 // AliL3ClustFinderNew
24 // The current cluster finder for HLT
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.
33 // There are several setters which control the behaviour:
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
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);
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();
84 ClassImp(AliL3ClustFinderNew)
86 AliL3ClustFinderNew::AliL3ClustFinderNew()
101 AliL3ClustFinderNew::~AliL3ClustFinderNew()
105 void AliL3ClustFinderNew::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
108 fMaxNClusters = nmaxpoints;
109 fCurrentSlice = slice;
110 fCurrentPatch = patch;
111 fFirstRow = firstrow;
115 void AliL3ClustFinderNew::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
118 fMaxNClusters = nmaxpoints;
119 fCurrentSlice = slice;
120 fCurrentPatch = patch;
121 fFirstRow=AliL3Transform::GetFirstRow(patch);
122 fLastRow=AliL3Transform::GetLastRow(patch);
125 void AliL3ClustFinderNew::SetOutputArray(AliL3SpacePointData *pt)
127 fSpacePointData = pt;
130 void AliL3ClustFinderNew::Read(UInt_t ndigits,AliL3DigitRowData *ptr)
132 fNDigitRowData = ndigits;
136 void AliL3ClustFinderNew::ProcessDigits()
138 //Loop over rows, and call processrow
140 AliL3DigitRowData *tempPt = (AliL3DigitRowData*)fDigitRowData;
142 for(Int_t i=fFirstRow; i<=fLastRow; i++)
145 if((Int_t)tempPt->fRow!=fCurrentRow){
146 LOG(AliL3Log::kWarning,"AliL3ClustFinderNew::ProcessDigits","Digits")
147 <<"Row number should match! "<<tempPt->fRow<<" "<<fCurrentRow<<ENDLOG;
151 Byte_t *tmp = (Byte_t*)tempPt;
152 Int_t size = sizeof(AliL3DigitRowData) + tempPt->fNDigit*sizeof(AliL3DigitData);
154 tempPt = (AliL3DigitRowData*)tmp;
156 LOG(AliL3Log::kInformational,"AliL3ClustFinderNew::ProcessDigits","Space points")
157 <<"Cluster finder found "<<fNClusters<<" clusters in slice "<<fCurrentSlice
158 <<" patch "<<fCurrentPatch<<ENDLOG;
161 void AliL3ClustFinderNew::ProcessRow(AliL3DigitRowData *tempPt)
164 UInt_t last_pad = 123456789;
166 ClusterData *pad1[5000]; //2 lists for internal memory=2pads
167 ClusterData *pad2[5000]; //2 lists for internal memory=2pads
168 ClusterData clusterlist[10000]; //Clusterlist
170 ClusterData **currentPt; //List of pointers to the current pad
171 ClusterData **previousPt; //List of pointers to the previous pad
174 UInt_t n_previous=0,n_current=0,n_total=0;
176 //Loop over sequences of this row:
177 for(UInt_t bin=0; bin<tempPt->fNDigit; bin++)
179 AliL3DigitData *data = tempPt->fDigitData;
180 if(data[bin].fPad != last_pad)
185 if(currentPt == pad2)
195 n_previous = n_current;
197 if(bin[data].fPad != last_pad+1)
199 //this happens if there is a pad with no signal.
200 n_previous = n_current = 0;
202 last_pad = data[bin].fPad;
205 Bool_t new_cluster = kTRUE;
206 UInt_t seq_charge=0,seq_average=0,seq_error=0;
207 UInt_t last_charge=0,last_was_falling=0;
212 redo: //This is a goto.
220 last_was_falling = 0;
223 while(1) //Loop over current sequence
225 if(data[bin].fTime >= AliL3Transform::GetNTimeBins())
227 LOG(AliL3Log::kFatal,"AliL3ClustFinderNew::ProcessRow","Digits")
228 <<"Timebin out of range "<<(Int_t)data[bin].fTime<<ENDLOG;
232 //Get the current ADC-value
233 UInt_t charge = data[bin].fCharge;
237 //Check if the last pixel in the sequence is smaller than this
238 if(charge > last_charge)
246 else last_was_falling = 1; //last pixel was larger than this
247 last_charge = charge;
250 //Sum the total charge of this sequence
251 seq_charge += charge;
252 seq_average += data[bin].fTime*charge;
253 seq_error += data[bin].fTime*data[bin].fTime*charge;
255 //Check where to stop:
256 if(bin >= tempPt->fNDigit - 1) //out of range
258 if(data[bin+1].fPad != data[bin].fPad) //new pad
260 if(data[bin+1].fTime != data[bin].fTime+1) //end of sequence
264 }//end loop over sequence
266 //Calculate mean of sequence:
269 seq_mean = seq_average/seq_charge;
272 LOG(AliL3Log::kFatal,"AliL3ClustFinderNew::ProcessRow","Data")
273 <<"Error in data given to the cluster finder"<<ENDLOG;
278 //Calculate mean in pad direction:
279 Int_t pad_mean = seq_charge*data[bin].fPad;
280 Int_t pad_error = data[bin].fPad*pad_mean;
282 //Compare with results on previous pad:
283 for(UInt_t p=0; p<n_previous; p++)
285 //dont merge sequences on the same pad twice
286 if(previousPt[p]->fLastMergedPad==data[bin].fPad) continue;
288 Int_t difference = seq_mean - previousPt[p]->fMean;
289 if(difference < -fMatch) break;
291 if(difference <= fMatch) //There is a match here!!
293 ClusterData *local = previousPt[p];
297 if(seq_charge > local->fLastCharge)
299 if(local->fChargeFalling) //The previous pad was falling
301 break; //create a new cluster
305 local->fChargeFalling = 1;
306 local->fLastCharge = seq_charge;
309 //Don't create a new cluster, because we found a match
310 new_cluster = kFALSE;
312 //Update cluster on current pad with the matching one:
313 local->fTotalCharge += seq_charge;
314 local->fPad += pad_mean;
315 local->fPad2 += pad_error;
316 local->fTime += seq_average;
317 local->fTime2 += seq_error;
318 local->fMean = seq_mean;
319 local->fFlags++; //means we have more than one pad
320 local->fLastMergedPad = data[bin].fPad;
322 currentPt[n_current] = local;
326 } //Checking for match at previous pad
327 } //Loop over results on previous pad.
331 //Start a new cluster. Add it to the clusterlist, and update
332 //the list of pointers to clusters in current pad.
333 //current pad will be previous pad on next pad.
335 //Add to the clusterlist:
336 ClusterData *tmp = &clusterlist[n_total];
337 tmp->fTotalCharge = seq_charge;
338 tmp->fPad = pad_mean;
339 tmp->fPad2 = pad_error;
340 tmp->fTime = seq_average;
341 tmp->fTime2 = seq_error;
342 tmp->fMean = seq_mean;
343 tmp->fFlags = 0; //flags for single pad clusters
344 tmp->fLastMergedPad = data[bin].fPad;
348 tmp->fChargeFalling = 0;
349 tmp->fLastCharge = seq_charge;
352 //Update list of pointers to previous pad:
353 currentPt[n_current] = &clusterlist[n_total];
359 if(new_bin >= 0) goto redo;
360 }//Loop over digits on this padrow
362 WriteClusters(n_total,clusterlist);
365 void AliL3ClustFinderNew::WriteClusters(Int_t n_clusters,ClusterData *list)
367 Int_t thisrow,thissector;
368 UInt_t counter = fNClusters;
370 for(int j=0; j<n_clusters; j++)
372 if(!list[j].fFlags) continue; //discard single pad clusters
373 if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
376 Float_t fpad =(Float_t)list[j].fPad /(Float_t)list[j].fTotalCharge;
377 Float_t fpad2=fXYErr*fXYErr; //fixed given error
378 Float_t ftime =(Float_t)list[j].fTime /(Float_t)list[j].fTotalCharge;
379 Float_t ftime2=fZErr*fZErr; //fixed given error
381 if(fCalcerr) { //calc the errors, otherwice take the fixed error
382 Int_t patch = AliL3Transform::GetPatch(fCurrentRow);
384 Float_t sy2=(Float_t)list[j].fPad2/(Float_t)list[j].fTotalCharge - fpad*fpad;
386 LOG(AliL3Log::kError,"AliL3ClustFinderNew::WriteClusters","Cluster width")
387 <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
391 fpad2 = (sy2 + 1./12)*AliL3Transform::GetPadPitchWidth(patch)*AliL3Transform::GetPadPitchWidth(patch);
393 fpad2*=0.108; //constants are from offline studies
397 } else fpad2=sy2; //take the width not the error
399 Float_t sz2=(Float_t)list[j].fTime2/(Float_t)list[j].fTotalCharge - ftime*ftime;
401 LOG(AliL3Log::kError,"AliL3ClustFinderNew::WriteClusters","Cluster width")
402 <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
406 ftime2 = (sz2 + 1./12)*AliL3Transform::GetZWidth()*AliL3Transform::GetZWidth();
408 ftime2 *= 0.169; //constants are from offline studies
412 } else ftime2=sz2; //take the width, not the error
416 cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
419 AliL3Transform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
420 AliL3Transform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
422 if(xyz[0]==0) LOG(AliL3Log::kError,"AliL3ClustFinder","Cluster Finder")
423 <<AliL3Log::kDec<<"Zero cluster"<<ENDLOG;
424 if(fNClusters >= fMaxNClusters)
426 LOG(AliL3Log::kError,"AliL3ClustFinder::WriteClusters","Cluster Finder")
427 <<AliL3Log::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
431 fSpacePointData[counter].fX = xyz[0];
432 fSpacePointData[counter].fY = xyz[1];
433 fSpacePointData[counter].fZ = xyz[2];
436 fSpacePointData[counter].fX = fCurrentRow;
437 fSpacePointData[counter].fY = fpad;
438 fSpacePointData[counter].fZ = ftime;
441 fSpacePointData[counter].fCharge = list[j].fTotalCharge;
442 fSpacePointData[counter].fPadRow = fCurrentRow;
443 fSpacePointData[counter].fSigmaY2 = fpad2;
444 fSpacePointData[counter].fSigmaZ2 = ftime2;
446 Int_t patch=fCurrentPatch;
447 if(patch==-1) patch=0; //never store negative patch number
448 fSpacePointData[counter].fID = counter
449 +((fCurrentSlice&0x7f)<<25)+((patch&0x7)<<22);//Uli
452 GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
454 fSpacePointData[counter].fTrackID[0] = trackID[0];
455 fSpacePointData[counter].fTrackID[1] = trackID[1];
456 fSpacePointData[counter].fTrackID[2] = trackID[2];
458 //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;
467 void AliL3ClustFinderNew::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
469 AliL3DigitRowData *rowPt = (AliL3DigitRowData*)fDigitRowData;
471 trackID[0]=trackID[1]=trackID[2]=-2;
472 //cout<<"Looking for pad "<<pad<<" time "<<time<<endl;
473 for(Int_t i=fFirstRow; i<=fLastRow; i++){
474 if(rowPt->fRow < (UInt_t)fCurrentRow){
475 AliL3MemHandler::UpdateRowPointer(rowPt);
478 AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
479 for(UInt_t j=0; j<rowPt->fNDigit; j++){
480 Int_t cpad = digPt[j].fPad;
481 Int_t ctime = digPt[j].fTime;
482 if(cpad != pad) continue;
483 if(ctime != time) continue;
485 trackID[0] = digPt[j].fTrackID[0];
486 trackID[1] = digPt[j].fTrackID[1];
487 trackID[2] = digPt[j].fTrackID[2];
489 //cout<<"Reading row "<<fCurrentRow<<" pad "<<cpad<<" time "<<ctime<<" trackID "<<digPt[j].fTrackID[0]<<endl;