]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/src/AliL3ClustFinderNew.cxx
Merged HLT tag v1-2 with ALIROOT tag v3-09-Release.
[u/mrichter/AliRoot.git] / HLT / src / AliL3ClustFinderNew.cxx
1 //$Id$
2
3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright &copy ASV 
5
6 #include "AliL3StandardIncludes.h"
7
8 #include "AliL3Logging.h"
9 #include "AliL3ClustFinderNew.h"
10 #include "AliL3DigitData.h"
11 #include "AliL3Transform.h"
12 #include "AliL3SpacePointData.h"
13 #include "AliL3MemHandler.h"
14
15 #if GCCVERSION == 3
16 using namespace std;
17 #endif
18
19 /** \class AliL3ClustFinderNew
20 <pre>
21 //_____________________________________________________________
22 // AliL3ClustFinderNew
23 //
24 // The current cluster finder for HLT
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 */
83
84 ClassImp(AliL3ClustFinderNew)
85
86 AliL3ClustFinderNew::AliL3ClustFinderNew()
87 {
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
101 AliL3ClustFinderNew::~AliL3ClustFinderNew()
102 {
103 }
104
105 void AliL3ClustFinderNew::InitSlice(Int_t slice,Int_t patch,Int_t firstrow, Int_t lastrow,Int_t nmaxpoints)
106 {
107   fNClusters = 0;
108   fMaxNClusters = nmaxpoints;
109   fCurrentSlice = slice;
110   fCurrentPatch = patch;
111   fFirstRow = firstrow;
112   fLastRow = lastrow;
113 }
114
115 void AliL3ClustFinderNew::InitSlice(Int_t slice,Int_t patch,Int_t nmaxpoints)
116 {
117   fNClusters = 0;
118   fMaxNClusters = nmaxpoints;
119   fCurrentSlice = slice;
120   fCurrentPatch = patch;
121   fFirstRow=AliL3Transform::GetFirstRow(patch);
122   fLastRow=AliL3Transform::GetLastRow(patch);
123 }
124
125 void AliL3ClustFinderNew::SetOutputArray(AliL3SpacePointData *pt)
126 {
127   fSpacePointData = pt;
128 }
129
130 void AliL3ClustFinderNew::Read(UInt_t ndigits,AliL3DigitRowData *ptr)
131 {
132   fNDigitRowData = ndigits;
133   fDigitRowData = ptr;
134 }
135
136 void AliL3ClustFinderNew::ProcessDigits()
137 {
138   //Loop over rows, and call processrow
139   
140   
141   AliL3DigitRowData *tempPt = (AliL3DigitRowData*)fDigitRowData;
142   
143   for(Int_t i=fFirstRow; i<=fLastRow; i++)
144     {
145       fCurrentRow = i;
146       ProcessRow(tempPt);
147       Byte_t *tmp = (Byte_t*)tempPt;
148       Int_t size = sizeof(AliL3DigitRowData) + tempPt->fNDigit*sizeof(AliL3DigitData);
149       tmp += size;
150       tempPt = (AliL3DigitRowData*)tmp;
151     }
152   LOG(AliL3Log::kInformational,"AliL3ClustFinderNew::WriteClusters","Space points")
153     <<"Cluster finder found "<<fNClusters<<" clusters in slice "<<fCurrentSlice
154     <<" patch "<<fCurrentPatch<<ENDLOG;
155 }
156
157 void AliL3ClustFinderNew::ProcessRow(AliL3DigitRowData *tempPt)
158 {
159
160   UInt_t last_pad = 123456789;
161
162   ClusterData *pad1[5000]; //2 lists for internal memory=2pads
163   ClusterData *pad2[5000]; //2 lists for internal memory=2pads
164   ClusterData clusterlist[10000]; //Clusterlist
165
166   ClusterData **currentPt;  //List of pointers to the current pad
167   ClusterData **previousPt; //List of pointers to the previous pad
168   currentPt = pad2;
169   previousPt = pad1;
170   UInt_t n_previous=0,n_current=0,n_total=0;
171
172   //Loop over sequences of this row:
173   for(UInt_t bin=0; bin<tempPt->fNDigit; bin++)
174     {
175       AliL3DigitData *data = tempPt->fDigitData;
176       if(data[bin].fPad != last_pad)
177         {
178           //This is a new pad
179           
180           //Switch the lists:
181           if(currentPt == pad2)
182             {
183               currentPt = pad1;
184               previousPt = pad2;
185             }
186           else 
187             {
188               currentPt = pad2;
189               previousPt = pad1;
190             }
191           n_previous = n_current;
192           n_current = 0;
193           if(bin[data].fPad != last_pad+1)
194             {
195               //this happens if there is a pad with no signal.
196               n_previous = n_current = 0;
197             }
198           last_pad = data[bin].fPad;
199         }
200
201       Bool_t new_cluster = kTRUE;
202       UInt_t seq_charge=0,seq_average=0,seq_error=0;
203       UInt_t last_charge=0,last_was_falling=0;
204       Int_t new_bin=-1;
205
206       if(fDeconvTime)
207         {
208         redo: //This is a goto.
209           if(new_bin > -1)
210             {
211               bin = new_bin;
212               new_bin = -1;
213             }
214           
215           last_charge=0;
216           last_was_falling = 0;
217         }
218       
219       while(1) //Loop over current sequence
220         {
221           if(data[bin].fTime >= AliL3Transform::GetNTimeBins())
222             {
223               LOG(AliL3Log::kFatal,"AliL3ClustFinderNew::ProcessRow","Digits")
224                 <<"Timebin out of range "<<(Int_t)data[bin].fTime<<ENDLOG;
225               break;
226             }
227
228           //Get the current ADC-value
229           UInt_t charge = data[bin].fCharge;
230           
231           if(fDeconvTime)
232             {
233               //Check if the last pixel in the sequence is smaller than this
234               if(charge > last_charge)
235                 {
236                   if(last_was_falling)
237                     {
238                       new_bin = bin;
239                       break;
240                     }
241                 }
242               else last_was_falling = 1; //last pixel was larger than this
243               last_charge = charge;
244             }
245           
246           //Sum the total charge of this sequence
247           seq_charge += charge;
248           seq_average += data[bin].fTime*charge;
249           seq_error += data[bin].fTime*data[bin].fTime*charge;
250
251           //Check where to stop:
252           if(bin >= tempPt->fNDigit - 1) //out of range
253             break;
254           if(data[bin+1].fPad != data[bin].fPad) //new pad
255             break;
256           if(data[bin+1].fTime != data[bin].fTime+1) //end of sequence
257             break;
258           
259           bin++;
260         }//end loop over sequence
261       
262       //Calculate mean of sequence:
263       Int_t seq_mean=0;
264       if(seq_charge)
265         seq_mean = seq_average/seq_charge;
266       else
267         {
268           LOG(AliL3Log::kFatal,"AliL3ClustFinderNew::ProcessRow","Data")
269             <<"Error in data given to the cluster finder"<<ENDLOG;
270           seq_mean = 1;
271           seq_charge = 1;
272         }
273       
274       //Calculate mean in pad direction:
275       Int_t pad_mean = seq_charge*data[bin].fPad;
276       Int_t pad_error = data[bin].fPad*pad_mean;
277
278       //Compare with results on previous pad:
279       for(UInt_t p=0; p<n_previous; p++)
280         {
281           //dont merge sequences on the same pad twice
282           if(previousPt[p]->fLastMergedPad==data[bin].fPad) continue;
283
284           Int_t difference = seq_mean - previousPt[p]->fMean;
285           if(difference < -fMatch) break;
286
287           if(difference <= fMatch) //There is a match here!!
288             {
289               ClusterData *local = previousPt[p];
290
291               if(fDeconvPad)
292                 {
293                   if(seq_charge > local->fLastCharge)
294                     {
295                       if(local->fChargeFalling) //The previous pad was falling
296                         {                       
297                           break; //create a new cluster
298                         }                   
299                     }
300                   else
301                     local->fChargeFalling = 1;
302                   local->fLastCharge = seq_charge;
303                 }
304               
305               //Don't create a new cluster, because we found a match
306               new_cluster = kFALSE;
307               
308               //Update cluster on current pad with the matching one:
309               local->fTotalCharge += seq_charge;
310               local->fPad += pad_mean;
311               local->fPad2 += pad_error;
312               local->fTime += seq_average;
313               local->fTime2 += seq_error;
314               local->fMean = seq_mean;
315               local->fFlags++; //means we have more than one pad 
316               local->fLastMergedPad = data[bin].fPad;
317
318               currentPt[n_current] = local;
319               n_current++;
320               
321               break;
322             } //Checking for match at previous pad
323         } //Loop over results on previous pad.
324       
325       if(new_cluster)
326         {
327           //Start a new cluster. Add it to the clusterlist, and update
328           //the list of pointers to clusters in current pad.
329           //current pad will be previous pad on next pad.
330
331           //Add to the clusterlist:
332           ClusterData *tmp = &clusterlist[n_total];
333           tmp->fTotalCharge = seq_charge;
334           tmp->fPad = pad_mean;
335           tmp->fPad2 = pad_error;
336           tmp->fTime = seq_average;
337           tmp->fTime2 = seq_error;
338           tmp->fMean = seq_mean;
339           tmp->fFlags = 0;  //flags for single pad clusters
340           tmp->fLastMergedPad = data[bin].fPad;
341
342           if(fDeconvPad)
343             {
344               tmp->fChargeFalling = 0;
345               tmp->fLastCharge = seq_charge;
346             }
347
348           //Update list of pointers to previous pad:
349           currentPt[n_current] = &clusterlist[n_total];
350           n_total++;
351           n_current++;
352         }
353
354       if(fDeconvTime)
355         if(new_bin >= 0) goto redo;
356     }//Loop over digits on this padrow
357   
358   WriteClusters(n_total,clusterlist);
359 }
360
361 void AliL3ClustFinderNew::WriteClusters(Int_t n_clusters,ClusterData *list)
362 {
363   Int_t thisrow,thissector;
364   UInt_t counter = fNClusters;
365   
366   for(int j=0; j<n_clusters; j++)
367     {
368       if(!list[j].fFlags) continue; //discard single pad clusters
369       if(list[j].fTotalCharge < fThreshold) continue; //noise cluster
370
371       Float_t xyz[3];      
372       Float_t fpad =(Float_t)list[j].fPad /(Float_t)list[j].fTotalCharge;
373       Float_t fpad2=fXYErr*fXYErr; //fixed given error
374       Float_t ftime =(Float_t)list[j].fTime /(Float_t)list[j].fTotalCharge;
375       Float_t ftime2=fZErr*fZErr;  //fixed given error
376
377       if(fCalcerr) { //calc the errors, otherwice take the fixed error 
378         Int_t patch = AliL3Transform::GetPatch(fCurrentRow);
379
380         Float_t sy2=(Float_t)list[j].fPad2/(Float_t)list[j].fTotalCharge - fpad*fpad;
381         if(sy2 < 0) {
382             LOG(AliL3Log::kError,"AliL3ClustFinderNew::WriteClusters","Cluster width")
383               <<"SigmaY2 negative "<<sy2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
384             continue;
385         } else {
386           if(!fRawSP){
387             fpad2 = (sy2 + 1./12)*AliL3Transform::GetPadPitchWidth(patch)*AliL3Transform::GetPadPitchWidth(patch);
388             if(sy2 != 0){
389               fpad2*=0.108; //constants are from offline studies
390               if(patch<2)
391                 fpad2*=2.07;
392             }
393           } else fpad2=sy2; //take the width not the error
394         }
395         Float_t sz2=(Float_t)list[j].fTime2/(Float_t)list[j].fTotalCharge - ftime*ftime;
396         if(sz2 < 0){
397           LOG(AliL3Log::kError,"AliL3ClustFinderNew::WriteClusters","Cluster width")
398             <<"SigmaZ2 negative "<<sz2<<" on row "<<fCurrentRow<<" "<<fpad<<" "<<ftime<<ENDLOG;
399           continue;
400         } else {
401           if(!fRawSP){
402             ftime2 = (sz2 + 1./12)*AliL3Transform::GetZWidth()*AliL3Transform::GetZWidth();
403             if(sz2 != 0) {
404               ftime2 *= 0.169; //constants are from offline studies
405               if(patch<2)
406                 ftime2 *= 1.77;
407             }
408           } else ftime2=sz2; //take the width, not the error
409         }
410       }
411       if(fStdout==kTRUE)
412         cout<<"WriteCluster: padrow "<<fCurrentRow<<" pad "<<fpad << " +- "<<fpad2<<" time "<<ftime<<" +- "<<ftime2<<" charge "<<list[j].fTotalCharge<<endl;
413       
414       if(!fRawSP){
415         AliL3Transform::Slice2Sector(fCurrentSlice,fCurrentRow,thissector,thisrow);
416         AliL3Transform::Raw2Local(xyz,thissector,thisrow,fpad,ftime);
417
418         if(xyz[0]==0) LOG(AliL3Log::kError,"AliL3ClustFinder","Cluster Finder")
419           <<AliL3Log::kDec<<"Zero cluster"<<ENDLOG;
420         if(fNClusters >= fMaxNClusters)
421           {
422             LOG(AliL3Log::kError,"AliL3ClustFinder::WriteClusters","Cluster Finder")
423               <<AliL3Log::kDec<<"Too many clusters "<<fNClusters<<ENDLOG;
424             return;
425           }  
426
427         fSpacePointData[counter].fX = xyz[0];
428         fSpacePointData[counter].fY = xyz[1];
429         fSpacePointData[counter].fZ = xyz[2];
430       } else {
431         fSpacePointData[counter].fCharge = list[j].fTotalCharge;
432         fSpacePointData[counter].fX = fCurrentRow;
433         fSpacePointData[counter].fY = fpad;
434         fSpacePointData[counter].fZ = ftime;
435       }
436
437       fSpacePointData[counter].fPadRow = fCurrentRow;
438       fSpacePointData[counter].fSigmaY2 = fpad2;
439       fSpacePointData[counter].fSigmaZ2  = ftime2;
440       fSpacePointData[counter].fID = counter
441         +((fCurrentSlice&0x7f)<<25)+((fCurrentPatch&0x7)<<22);//Uli
442 #ifdef do_mc
443       Int_t trackID[3];
444       GetTrackID((Int_t)rint(fpad),(Int_t)rint(ftime),trackID);
445
446       fSpacePointData[counter].fTrackID[0] = trackID[0];
447       fSpacePointData[counter].fTrackID[1] = trackID[1];
448       fSpacePointData[counter].fTrackID[2] = trackID[2];
449
450       //cout<<"padrow "<<fCurrentRow<<" pad "<<(Int_t)rint(fpad)<<" time "<<(Int_t)rint(ftime)<<" Trackid "<<trackID[0]<<endl;
451 #endif
452       
453       fNClusters++;
454       counter++;
455     }
456 }
457
458 #ifdef do_mc
459 void AliL3ClustFinderNew::GetTrackID(Int_t pad,Int_t time,Int_t *trackID)
460 {
461   AliL3DigitRowData *rowPt = (AliL3DigitRowData*)fDigitRowData;
462   
463   trackID[0]=trackID[1]=trackID[2]=-2;
464   //cout<<"Looking for pad "<<pad<<" time "<<time<<endl;
465   for(Int_t i=fFirstRow; i<=fLastRow; i++){
466     if(rowPt->fRow < (UInt_t)fCurrentRow){
467       AliL3MemHandler::UpdateRowPointer(rowPt);
468       continue;
469     }
470     AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
471     for(UInt_t j=0; j<rowPt->fNDigit; j++){
472       Int_t cpad = digPt[j].fPad;
473       Int_t ctime = digPt[j].fTime;
474       if(cpad != pad) continue;
475       if(ctime != time) continue;
476
477       trackID[0] = digPt[j].fTrackID[0];
478       trackID[1] = digPt[j].fTrackID[1];
479       trackID[2] = digPt[j].fTrackID[2];
480       
481       //cout<<"Reading row "<<fCurrentRow<<" pad "<<cpad<<" time "<<ctime<<" trackID "<<digPt[j].fTrackID[0]<<endl;
482       break;
483     }
484     break;
485   }
486 }
487 #endif