]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/comp/AliL3Modeller.cxx
cde915853119214d1e1df2856c5e9ae3ba72ecd4
[u/mrichter/AliRoot.git] / HLT / comp / AliL3Modeller.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 "AliL3Modeller.h"
9 #include "AliL3MemHandler.h"
10 #ifdef use_aliroot
11 #include "AliL3FileHandler.h"
12 #endif
13 #include "AliL3TrackArray.h"
14 #include "AliL3ModelTrack.h"
15 #include "AliL3DigitData.h"
16 #include "AliL3Transform.h"
17
18 #if GCCVERSION == 3
19 using namespace std;
20 #endif
21
22 //_____________________________________________________________
23 // AliL3Modeller
24 //
25 // Class for modeling TPC data.
26 // 
27 // This performs the cluster finding, based on track parameters.
28 // Basically it propagates the tracks to all padrows, and looks 
29 // for a corresponding cluster. For the moment only cog is calculated,
30 // and no deconvolution is done. 
31
32 ClassImp(AliL3Modeller)
33
34 AliL3Modeller::AliL3Modeller()
35 {
36   fMemHandler=0;
37   fTracks=0;
38   fTrackThreshold=0;
39   SetOverlap();
40   SetTrackThreshold();
41   SetSearchRange();
42 }
43
44
45 AliL3Modeller::~AliL3Modeller()
46 {
47   if(fMemHandler)
48     delete fMemHandler;
49   if(fTracks)
50     delete fTracks;
51 }
52
53 void AliL3Modeller::Init(Int_t slice,Int_t patch,Char_t *trackdata,Char_t *path,Bool_t houghtracks,Bool_t binary)
54 {
55   fSlice = slice;
56   fPatch = patch;
57
58   sprintf(fPath,"%s",path);
59   
60   fTracks = new AliL3TrackArray("AliL3ModelTrack");
61   
62   Char_t fname[100];
63   AliL3MemHandler *file = new AliL3MemHandler();
64   //sprintf(fname,"%s/tracks_tr_%d_0.raw",trackdata,fSlice); //output tracks from the tracker (no merging)
65   sprintf(fname,"%s/tracks_ho_%d.raw",trackdata,fSlice);
66   if(!file->SetBinaryInput(fname))
67     {
68       cerr<<"AliL3Modeller::Init : Error opening trackfile: "<<fname<<endl;
69       return;
70     }
71   file->Binary2TrackArray(fTracks);
72   file->CloseBinaryInput();
73   delete file;
74   
75
76   if(!houghtracks)
77     fTracks->QSort();
78   
79   for(Int_t i=0; i<fTracks->GetNTracks(); i++)
80     {
81       AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
82       if(!track) continue;
83       track->Init(fSlice,fPatch);
84
85       //Only if the tracks has been merged across sector boundaries:
86       //if(!houghtracks)
87       //track->Rotate(fSlice,kTRUE); //!!!!!!!!!!!!!!!!!!!
88       
89       track->CalculateHelix();
90     }    
91   
92   CalculateCrossingPoints();
93   
94   CheckForOverlaps();
95   
96   UInt_t ndigits=0;
97   AliL3DigitRowData *digits=0;
98 #ifdef use_aliroot
99   fMemHandler = new AliL3FileHandler();
100   fMemHandler->Init(slice,patch);
101   if(binary == kFALSE)
102     {
103       sprintf(fname,"%s/digitfile.root",fPath);
104       fMemHandler->SetAliInput(fname);
105       digits = fMemHandler->AliDigits2Memory(ndigits);
106     }
107   else
108     {
109       sprintf(fname,"%sdigits_%d_%d.raw",fPath,fSlice,fPatch);
110       if(!fMemHandler->SetBinaryInput(fname))
111         {
112           cerr<<"AliL3Modeller::Init : Error opening file "<<fname<<endl;
113           return;
114         }
115       digits=(AliL3DigitRowData*)fMemHandler->CompBinary2Memory(ndigits);
116     }
117 #else
118   fMemHandler = new AliL3MemHandler();
119   fMemHandler->Init(slice,patch);
120   if(binary == kFALSE)
121     {
122       cerr<<"AliL3Modeller::Init : Compile with AliROOT if you want rootfile as input"<<endl;
123       return;
124     }
125   else
126     {
127       sprintf(fname,"%sdigits_%d_%d.raw",fPath,fSlice,fPatch);
128       if(!fMemHandler->SetBinaryInput(fname))
129         {
130           cerr<<"AliL3Modeller::Init : Error opening file "<<fname<<endl;
131           return;
132         }
133     }
134   digits=(AliL3DigitRowData*)fMemHandler->CompBinary2Memory(ndigits);
135 #endif
136   
137   SetInputData(digits);
138 }
139
140 void AliL3Modeller::FindClusters()
141 {
142   cout<<"AliL3Modeller::FindClusters : Processing slice "<<fSlice<<" patch "<<fPatch<<endl;
143   if(!fTracks)
144     {
145       cerr<<"AliL3Modeller::Process : No tracks"<<endl;
146       return;
147     }
148   if(!fRowData)
149     {
150       cerr<<"AliL3Modeller::Process : No data "<<endl;
151       return;
152     }
153   
154   AliL3DigitRowData *rowPt = fRowData;
155   AliL3DigitData *digPt=0;
156
157   Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
158   Int_t npads = AliL3Transform::GetNPads(AliL3Transform::GetLastRow(fPatch))+1;//Max num of pads.
159   Int_t bounds = ntimes*npads;
160   Digit *row = new Digit[bounds];
161   
162   Int_t seq_charge;
163   Int_t pad,time,index;
164   Short_t charge;
165   Cluster cluster;
166
167   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
168     {
169       fCurrentPadRow = i;
170       memset((void*)row,0,ntimes*npads*sizeof(Digit));
171       digPt = (AliL3DigitData*)rowPt->fDigitData;
172       //cout<<"Loading row "<<i<<" with "<<(Int_t)rowPt->fNDigit<<" digits"<<endl;
173       for(UInt_t j=0; j<rowPt->fNDigit; j++)
174         {
175           pad = digPt[j].fPad;
176           time = digPt[j].fTime;
177           charge = digPt[j].fCharge;
178           row[ntimes*pad+time].fCharge = charge;
179           row[ntimes*pad+time].fUsed = kFALSE;
180           //cout<<"Row "<<i<<" pad "<<pad<<" time "<<time<<" charge "<<charge<<endl;
181         }
182       
183       for(Int_t k=0; k<fTracks->GetNTracks(); k++)
184         {
185           AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(k);
186           if(!track) continue;
187           
188           if(track->GetPadHit(i)<0 || track->GetTimeHit(i)<0 || track->GetOverlap(i)>=0)
189             {
190               track->SetCluster(i,0,0,0,0,0,0); //The track has left the patch.
191               continue;
192             }
193           
194           Int_t hitpad = (Int_t)rint(track->GetPadHit(i));
195           Int_t hittime = (Int_t)rint(track->GetTimeHit(i));
196           //cout<<"Checking track on row "<<i<<" with pad "<<hitpad<<" time "<<hittime<<endl;
197           pad = hitpad;
198           time = hittime;
199           
200           /*
201             if(row[ntimes*pad + time].fCharge == 0 || 
202             row[ntimes*pad + time].fUsed == kTRUE) //Bad track, or cluster has already been included.
203             {
204             track->SetCluster(i,0,0,0,0,0,0);
205             continue;
206             }
207           */
208           Int_t padsign=-1;
209           Int_t timesign=-1;
210           
211           memset(&cluster,0,sizeof(Cluster));
212           //cout<<"Processing padrow "<<i<<" with hittime "<<hittime<<" hitpad "<<hitpad<<" charge "<<row[ntimes*pad + time].fCharge<<" index "<<ntimes*pad + time<<endl;
213           Int_t npads=0;
214           Int_t last_mean = hittime;
215           while(1)//Process this padrow
216             {
217               if(pad < 0 || pad >= AliL3Transform::GetNPads(i)) 
218                 {
219                   //cout<<"Pad = "<<pad<<" on row "<<i<<endl;
220                   FillCluster(track,&cluster,i,npads);
221                   break;
222                 }
223               seq_charge=0;
224               timesign=-1;
225               time = hittime;
226               
227               while(1) //Process sequence on this pad:
228                 {
229                   if(time < 0 || time >= AliL3Transform::GetNTimeBins()) 
230                     break;
231                 
232                   index = ntimes*pad + time;
233                   if(index < 0 || index >= bounds)
234                     {
235                       cerr<<"AliL3Modeller::FindClusters : Index out of range : "<<index
236                         <<" on row "<<i<<" pad "<<pad<<" time "<<time<<endl;
237                       break;
238                     }
239                   
240                   charge = row[index].fCharge;
241                   if(charge==0 && timesign==-1) //zero charge on this timebin, perform checks:
242                     {
243                       if(seq_charge==0 && abs(time-hittime) <= fTimeSearch) //No charge found on this pad, look further.
244                         //if(seq_charge==0 && abs(time-last_mean) <= fTimeOverlap)
245                         {
246                           //cout<<"Sequence is zero, time "<<time<<" hittime "<<hittime<<" pad "<<pad<<" charge "<<charge<<" index "<<index<<endl;
247                           time--;
248                           continue;
249                         }
250                       else 
251                         {
252                           time = hittime+1;
253                           timesign=1;
254                           continue;
255                         }
256                     }
257                   else if(charge==0 && timesign==1)//zero charge on this timebin, perform checks:
258                     {
259                       if(seq_charge==0 && abs(time-hittime) <= fTimeSearch)//No charge found on this pad, look further
260                         //if(seq_charge==0 && abs(time-last_mean) <=fTimeOverlap)
261                         {
262                           time++;
263                           continue;
264                         }
265                       else //Boundary reached, or we have found the other end of the sequence, stop looking on this pad.
266                         {
267                           //if(fCurrentPadRow==31)
268                           //   cerr<<"Breaking off at pad "<<pad<<" and time "<<time<<endl;
269                           break;
270                         }
271                     }
272                   
273                   if(row[ntimes*pad+time].fUsed==kTRUE) //Don't use digits several times. This leads to mult. rec.tracks.
274                     {
275                       time += timesign;
276                       continue;
277                     }
278                   
279                   seq_charge += charge;
280                   
281                   //Update the cluster parameters with this timebin
282                   cluster.fTime += time*charge;
283                   cluster.fPad += pad*charge;
284                   cluster.fCharge += charge;
285                   cluster.fSigmaY2 += pad*pad*charge;
286                   cluster.fSigmaZ2 += time*time*charge;
287                   
288                   row[ntimes*pad+time].fUsed = kTRUE;
289                   time += timesign;
290                 }
291               
292               //Always compare with the current mean in time of the cluster under construction.
293               if(cluster.fCharge)
294                 last_mean = (Int_t)rint((Float_t)(cluster.fTime/cluster.fCharge));
295               
296               if(seq_charge)//There was something on this pad, so keep looking on the neighbouring pad
297                 {
298                   pad += padsign;
299                   npads++;
300                 }
301               else //Nothing more on this pad, goto next pad
302                 {
303                   if(padsign==-1) 
304                     {
305                       if(cluster.fCharge==0 && abs(pad-hitpad) <= fPadSearch && pad > 0)
306                         {
307                           //cout<<"Cluster is zero!"<<endl;
308                           pad--;     //In this case, we haven't found anything yet, 
309                           continue;  //so we will try to expand our search within the natural boundaries.
310                         }        
311                       else 
312                         {
313                           pad=hitpad+1;
314                           padsign=1; 
315                           continue;
316                         }
317                     }
318                   
319                   else if(padsign==1)
320                     {
321                       if(cluster.fCharge==0 && abs(pad-hitpad) <= fPadSearch && pad < AliL3Transform::GetNPads(i)-2)
322                         {
323                           //cout<<"Cluster is zero "<<endl;
324                           pad++;     //In this case, we haven't found anything yet, 
325                           continue;  //so we will try to expand our search within the natural boundaries.
326                         }
327                       else //We are out of range, or cluster if finished.
328                         {
329                           //if(fCurrentPadRow==31)
330                           //cout<<"Out of range; charge "<<cluster.fCharge<<" paddiff "<<abs(pad-hitpad)<<endl;
331                           FillCluster(track,&cluster,i,npads);
332                           break;
333                         }
334                     }
335                   else //Nothing more in this cluster
336                     {
337                       //if(fCurrentPadRow==31)
338                       //cout<<"Filling final cluster"<<endl;
339                       FillCluster(track,&cluster,i,npads);
340                       break;
341                     } 
342                 }
343             }
344           //cout<<"done"<<endl;
345         }
346       FillZeros(rowPt,row);
347       fMemHandler->UpdateRowPointer(rowPt);
348     }
349   delete [] row;
350   //cout<<"done processing"<<endl;
351   
352   
353   //Debug:
354   for(Int_t i=0; i<fTracks->GetNTracks(); i++)
355     {
356       AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
357       if(!track) continue;
358       if(track->GetNClusters() != AliL3Transform::GetNRows(fPatch))
359         cerr<<endl<<"Mismatching hitcounts; nclusters: "<<track->GetNClusters()<<" nrows "<<AliL3Transform::GetNRows(fPatch)<<endl<<endl;
360     }
361   
362 }
363
364 void AliL3Modeller::FillCluster(AliL3ModelTrack *track,Cluster *cluster,Int_t row,Int_t npads)
365 {
366   if(cluster->fCharge==0)
367     {
368       track->SetCluster(row,0,0,0,0,0,0);
369       return;
370     }
371   Float_t fcharge = (Float_t)cluster->fCharge;
372   Float_t fpad = ((Float_t)cluster->fPad/fcharge);
373   Float_t ftime = ((Float_t)cluster->fTime/fcharge);
374   Float_t sigmaY2,sigmaZ2;
375   CalcClusterWidth(cluster,sigmaY2,sigmaZ2);
376   track->SetCluster(row,fpad,ftime,fcharge,sigmaY2,sigmaZ2,npads);
377 }
378
379 void AliL3Modeller::FillZeros(AliL3DigitRowData *rowPt,Digit *row)
380 {
381   //Fill zero where data has been used.
382   
383   Int_t ntimes = AliL3Transform::GetNTimeBins()+1;
384   AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
385   for(UInt_t j=0; j<rowPt->fNDigit; j++)
386     {
387       Int_t pad = digPt[j].fPad;
388       Int_t time = digPt[j].fTime;
389       if(row[ntimes*pad+time].fUsed==kTRUE)
390         digPt[j].fCharge = 0;
391     }
392 }
393
394 void AliL3Modeller::WriteRemaining()
395 {
396   //Write remaining (nonzero) digits to file.
397   
398   AliL3DigitRowData *rowPt;
399   rowPt = (AliL3DigitRowData*)fRowData;
400   Int_t digitcount=0;
401   Int_t ndigits[(AliL3Transform::GetNRows(fPatch))];
402   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
403     {
404       AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
405       ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]=0;
406       for(UInt_t j=0; j<rowPt->fNDigit; j++)
407         {
408           if(digPt[j].fCharge==0) continue;
409           digitcount++;
410           ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]++;
411         }
412       //cout<<"Difference "<<(int)ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]<<" "<<(int)rowPt->fNDigit<<endl;
413       fMemHandler->UpdateRowPointer(rowPt);
414     }
415   
416   Int_t size = digitcount*sizeof(AliL3DigitData) + AliL3Transform::GetNRows(fPatch)*sizeof(AliL3DigitRowData);
417   Byte_t *data = new Byte_t[size];
418   memset(data,0,size);
419   AliL3DigitRowData *tempPt = (AliL3DigitRowData*)data;
420   rowPt = (AliL3DigitRowData*)fRowData;
421   
422   for(Int_t i=AliL3Transform::GetFirstRow(fPatch); i<=AliL3Transform::GetLastRow(fPatch); i++)
423     {
424       Int_t localcount=0;
425       tempPt->fRow = i;
426       tempPt->fNDigit = ndigits[(i-AliL3Transform::GetFirstRow(fPatch))];
427       AliL3DigitData *digPt = (AliL3DigitData*)rowPt->fDigitData;
428       for(UInt_t j=0; j<rowPt->fNDigit; j++)
429         {
430           if(digPt[j].fCharge==0) continue;
431           if(localcount >= ndigits[(i-AliL3Transform::GetFirstRow(fPatch))])
432             {
433               cerr<<"AliL3Modeller::WriteRemaining : Digitarray out of range!!"<<endl;
434               return;
435             }
436           tempPt->fDigitData[localcount].fCharge = digPt[j].fCharge;
437           tempPt->fDigitData[localcount].fPad = digPt[j].fPad;
438           tempPt->fDigitData[localcount].fTime = digPt[j].fTime;
439
440           localcount++;
441         }
442       if(ndigits[(i-AliL3Transform::GetFirstRow(fPatch))] != localcount)
443         {
444           cerr<<"AliL3Modeller::WriteRemaining : Mismatch in digitcount"<<endl;
445           return;
446         }
447       fMemHandler->UpdateRowPointer(rowPt);
448       Byte_t *tmp = (Byte_t*)tempPt;
449       Int_t size = sizeof(AliL3DigitRowData) + ndigits[(i-AliL3Transform::GetFirstRow(fPatch))]*sizeof(AliL3DigitData);
450       tmp += size;
451       tempPt = (AliL3DigitRowData*)tmp;
452     }
453
454   Char_t fname[100];
455   AliL3MemHandler *mem = new AliL3MemHandler();
456   sprintf(fname,"%s/comp/remains_%d_%d.raw",fPath,fSlice,fPatch);
457   mem->SetBinaryOutput(fname);
458   mem->Memory2CompBinary((UInt_t)AliL3Transform::GetNRows(fPatch),(AliL3DigitRowData*)data);
459   mem->CloseBinaryOutput();
460   delete mem;
461   delete [] data;
462 }
463
464
465 void AliL3Modeller::CalculateCrossingPoints()
466 {
467   //cout<<"Calculating crossing points on "<<fTracks->GetNTracks()<<" tracks"<<endl;
468   if(!fTracks)
469     {
470       cerr<<"AliL3Modeller::CalculateCrossingPoints(): No tracks"<<endl;
471       return;
472     }
473   Float_t hit[3];
474   
475   Int_t sector,row;
476   for(Int_t i=AliL3Transform::GetLastRow(fPatch); i>=AliL3Transform::GetFirstRow(fPatch); i--)
477     {
478       for(Int_t j=0; j<fTracks->GetNTracks(); j++)
479         {
480           AliL3ModelTrack *track = (AliL3ModelTrack*)fTracks->GetCheckedTrack(j);
481           if(!track) continue;
482
483           if(!track->GetCrossingPoint(i,hit)) 
484             {
485               //cerr<<"AliL3Modeller::CalculateCrossingPoints : Track "<<j<<" does not intersect row "<<i<<" :"<<endl<<
486               //" pt "<<track->GetPt()<<
487               //" tgl "<<track->GetTgl()<<" psi "<<track->GetPsi()<<" charge "<<track->GetCharge()<<endl;
488                 //"Center "<<track->GetCenterX()<<" "<<track->GetCenterY()<<endl<<endl<<
489                 //"--------"<<endl;
490               fTracks->Remove(j);
491               continue;
492             }
493           //cout<<"X "<<hit[0]<<" Y "<<hit[1]<<" Z "<<hit[2]<<" tgl "<<track->GetTgl()<<endl;
494           
495           AliL3Transform::Slice2Sector(fSlice,i,sector,row);
496           AliL3Transform::Local2Raw(hit,sector,row);
497           //cout<<"Pad "<<hit[1]<<" time "<<hit[2]<<" in sector "<<sector<<" row "<<row<<endl;
498           if(hit[1]<0 || hit[1]>AliL3Transform::GetNPads(i) ||
499              hit[2]<0 || hit[2]>AliL3Transform::GetNTimeBins())
500             {//Track is leaving the patch, so flag the track hits (<0)
501               track->SetPadHit(i,-1);
502               track->SetTimeHit(i,-1);
503               continue;
504             }
505           
506           
507           track->SetPadHit(i,hit[1]);
508           track->SetTimeHit(i,hit[2]);
509           
510           //if(hit[1]<0 || hit[2]>445)
511           //if(hit[2]<0 || hit[2]>445)
512           //cout<<"pad "<<hit[1]<<" time "<<hit[2]<<" pt "<<track->GetPt()<<" psi "<<track->GetPsi()<<" tgl "<<track->GetTgl()<<" firstpoint "<<track->GetFirstPointX()<<" "<<track->GetFirstPointY()<<" "<<track->GetFirstPointZ()<<endl;
513           //cout<<"Crossing pad "<<hit[1]<<" time "<<hit[2]<<endl;
514         }
515     }
516   fTracks->Compress();
517   //cout<<"And there are "<<fTracks->GetNTracks()<<" tracks remaining"<<endl;
518 }
519
520 void AliL3Modeller::CheckForOverlaps()
521 {
522   //Flag the tracks that overlap
523   
524   //cout<<"Checking for overlaps...";
525   Int_t counter=0;
526   for(Int_t i=0; i<fTracks->GetNTracks(); i++)
527     {
528       AliL3ModelTrack *track1 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(i);
529       if(!track1) continue;
530       for(Int_t j=i+1; j<fTracks->GetNTracks(); j++)
531         {
532           AliL3ModelTrack *track2 = (AliL3ModelTrack*)fTracks->GetCheckedTrack(j);
533           if(!track2) continue;
534           for(Int_t k=AliL3Transform::GetFirstRow(fPatch); k<=AliL3Transform::GetLastRow(fPatch); k++)
535             {
536               if(track1->GetPadHit(k)<0 || track1->GetTimeHit(k)<0 ||
537                  track2->GetPadHit(k)<0 || track2->GetTimeHit(k)<0)
538                 continue;
539               
540               if(track1->GetOverlap(k)>=0 || track2->GetOverlap(k)>=0) continue;
541               
542               if(abs((Int_t)rint(track1->GetPadHit(k))-(Int_t)rint(track2->GetPadHit(k))) <= fPadOverlap &&
543                  abs((Int_t)rint(track1->GetTimeHit(k))-(Int_t)rint(track2->GetTimeHit(k))) <= fTimeOverlap)
544                 {
545                   track2->SetOverlap(k,i);
546                   //track1->SetOverlap(k,j);
547                   counter++;
548                 }
549             }
550         }
551     }
552   //cout<<"found "<<counter<<" done"<<endl;
553 }
554
555
556 void AliL3Modeller::CalcClusterWidth(Cluster *cl,Float_t &sigmaY2,Float_t &sigmaZ2)
557 {
558   
559   Float_t padw,timew;
560   
561   padw = AliL3Transform::GetPadPitchWidth(fPatch);
562   
563   Float_t charge = (Float_t)cl->fCharge;
564   Float_t pad = (Float_t)cl->fPad/charge;
565   Float_t time = (Float_t)cl->fTime/charge;
566   Float_t s2 = (Float_t)cl->fSigmaY2/charge - pad*pad;
567   
568   //Save the sigmas in pad and time:
569   
570   sigmaY2 = (s2);// + 1./12);//*padw*padw;
571   
572   /*Constants added by offline
573     if(s2 != 0)
574     {
575     sigmaY2 = sigmaY2*0.108;
576     if(fPatch<3)
577     sigmaY2 = sigmaY2*2.07;
578     }
579   */
580
581   s2 = (Float_t)cl->fSigmaZ2/charge - time*time;
582   timew = AliL3Transform::GetZWidth();
583   sigmaZ2 = (s2);// +1./12);//*timew*timew;
584   
585
586   
587   /*Constants added by offline
588     if(s2 != 0)
589     {
590     sigmaZ2 = sigmaZ2*0.169;
591     if(fPatch < 3)
592     sigmaZ2 = sigmaZ2*1.77;
593     }
594   */
595 }
596