- fixed the format of the floats that become part of the output file name
[u/mrichter/AliRoot.git] / HLT / QA / tasks / macros / drawTHnSparse.C
1 // $Id$
2 /*
3  * Drawing macro for reading the THnSparse output of the 
4  * HLT/QA/tasks/AliAnalysisTaskHLTCentralBarrel.cxx task.
5  * 
6  * The cuts are user defined in lines 167-168 as arguments of the 
7  * function cutStsudies(...).
8  * 
9  * The input file contains information about the run number
10  * and date that will appear in the canvas title.
11  * 
12  * The cuts are turned into strings and incorporated in the
13  * name of the output file, which contains canvases with event
14  * and track properties for HLT and offline.
15  *  
16  * Since the run information is available, there will be a new
17  * folder created and the canvas ROOT files will be saved in there.
18  *
19  * The macro should be compiled before running:
20  *
21  * root[0] .L drawTHnSparse.C++
22  * root[1] drawTHnSparse("HLT-OFFLINE-CentralBarrel-comparison.root")
23  *
24  * @ingroup alihlt_qa
25  * @author Kalliopi.Kanaki@ift.uib.no 
26  */
27
28 #if !defined(__CINT__) || defined(__MAKECINT__)
29 #include "TSystem.h"
30 #include "TROOT.h"
31 #include "TFile.h"
32 #include "TString.h"
33 #include "TList.h"
34 #include "THnSparse.h"
35 #include "TCanvas.h"
36 #include "TText.h"
37 #include "TPaveText.h"
38 #include "TPaveStats.h"
39 #include "TH1D.h"
40 #include "TH2D.h"
41 #include "TLegend.h"
42 #include "TStyle.h"
43 #include "TPad.h"
44
45 #include <iostream>
46 //#include <sstream>
47 #include <cstdlib>
48
49 //using std::stringstream;
50 using std::endl;
51 #endif
52
53
54 //---------- forward declerations ---------------//
55
56 TString cutStudies( TCanvas* can1, TCanvas* can2, TCanvas* can3, TString folder,
57                     THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText,
58                     double minEta,   double maxEta,
59                     int minTrackMult,int maxTrackMult,
60                     double minPt,    double maxPt,
61                     double minDCAr,  double maxDCAr,
62                     double minDCAz,  double maxDCAz,
63                     int minTPCclus,  int maxTPCclus,
64                     int minITSclus,  int maxITSclus,
65                     int vertexStatus
66                   );
67 void printStats(TH1D *hlt, TH1D *off);
68 void defineYaxisMax(TH1D *hlt, TH1D *off);
69 void printLegend(TLegend *l, TH1D *hlt, TH1D *off);
70 void plotAid(TCanvas* can, THnSparse* hHLT, THnSparse* hOFF, TText* hText, TH1D *hlt, TH1D *off, TLegend *l, int size);    
71 void plot2D(TCanvas* can, THnSparse* h,
72             double minEta,    double maxEta,
73             double minPt,     double maxPt,
74             double minDCAr,   double maxDCAr,
75             double minDCAz,   double maxDCAz,
76             int minTPCclus,   int maxTPCclus,
77             int minITSclus,   int maxITSclus, 
78             int minTrackMult, int maxTrackMult
79            );
80 void plotEventQuantities(TCanvas* can, THnSparse* heventHLT, THnSparse* heventOFF, TText* hText);
81 TString fix1DTitle(const char* c);
82 TString fix2DTitle(const char* c1, const char* c2);
83 TString cutsToString( double minEta,    double maxEta,
84                       double minPt,     double maxPt,
85                       double minDCAr,   double maxDCAr,
86                       double minDCAz,   double maxDCAz,
87                       int minTPCclus,   int maxTPCclus,
88                       int minITSclus,   int maxITSclus, 
89                       int minTrackMult, int maxTrackMult,
90                       int VS
91                     );
92 void plotTrackQuantities( TCanvas* can, THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText,
93                           double minEta,    double maxEta,
94                           double minPt,     double maxPt,
95                           double minDCAr,   double maxDCAr,
96                           double minDCAz,   double maxDCAz,
97                           int minTPCclus,   int maxTPCclus,
98                           int minITSclus,   int maxITSclus, 
99                           int minTrackMult, int maxTrackMult,
100                           int VS
101                         );
102                         
103 vector<TString> outputNames;
104
105 //------------------------------------------------------------------//          
106                         
107 void drawTHnSparse(TString inputFile){
108  
109   gROOT->SetStyle("Plain");
110   gStyle->SetPalette(1);
111   gStyle->SetOptStat(10);
112   TH1::AddDirectory(kFALSE);
113
114   TFile *file = TFile::Open(inputFile);
115   if(!file){
116     printf("Error: No file %s in folder.\n", inputFile.Data());
117     return;
118   }
119
120   TList *list = static_cast<TList*>(file->Get("esd_thnsparse"));
121   if(!list){
122     printf("Error: No List contained in file %s.\n", inputFile.Data());
123     return;
124   }
125
126   THnSparseF *heventHLT = (THnSparseF*)list->FindObject("fEventHLT"); 
127   if(!heventHLT){
128       printf("Error: There is no HLT THnSparse object in file %s\n", inputFile.Data());
129   }
130   THnSparseF *heventOFF = (THnSparseF*)list->FindObject("fEventOFF");  
131   if(!heventOFF){
132       printf("Error: There is no OFF THnSparse object in file %s\n", inputFile.Data());
133   } 
134   THnSparseF *htrackHLT = (THnSparseF*)list->FindObject("fTrackHLT");
135   if(!htrackHLT){
136       printf("Error: No HLT THnSparse object found\n");
137       return;
138   } 
139   THnSparseF *htrackOFF = (THnSparseF*)list->FindObject("fTrackOFF");  
140   if(!htrackOFF){
141       printf("Error: No OFF THnSparse object found\n");
142       return;
143   }
144       
145   TText *hText = (TText*)list->FindObject("text");
146   if(!hText) printf("No hText\n");
147   
148   TString t = "event properties for ";
149   t+=hText->GetTitle();
150   
151   TString folder = hText->GetTitle();
152   folder.ReplaceAll(" ",""); 
153   folder.Remove(0,3);
154   folder.Remove(6,15);
155    
156   gSystem->Exec("mkdir "+folder);
157   
158   TCanvas *can0 = new TCanvas("can0",t,                            900,600); can0->Divide(3,2);  
159   TCanvas *can1 = new TCanvas("can1","track properties",          1100,900); can1->Divide(4,3);
160   TCanvas *can2 = new TCanvas("can2","2-D HLT track correlations",1200,800); can2->Divide(4,2);
161   TCanvas *can3 = new TCanvas("can3","2-D OFF track correlations",1200,800); can3->Divide(4,2);
162
163   plotEventQuantities(can0,heventHLT,heventOFF,hText);
164   can0->SaveAs(folder+"/event_properties.root");
165   can0->SaveAs(folder+"/event_properties.png");
166     
167   TString s = "";                                                       // eta   mult      pt     DCAr    DCAz    TPCclus ITSclus  vertexStatus
168   s = cutStudies(can1, can2, can3, folder, htrackHLT, htrackOFF, hText, -2, 2, 0, 20000, 0, 200, -20, 20, -20, 20,  0, 200, 0, 6, 2); outputNames.push_back(s); 
169   //s = cutStudies(can1, can2, can3, folder, htrackHLT, htrackOFF, hText, -2, 2, 0, 20000, 0, 200, -20, 20, -20, 20,  0, 200, 1, 6, 2); outputNames.push_back(s); 
170   
171   TCanvas *ov = new TCanvas("ov","overlaid histograms of track properties",1100,900);
172   ov->Divide(4,3);
173
174   TCanvas *ca[outputNames.size()]; 
175   TFile   *ff[outputNames.size()]; 
176   TPad    *pad[12]; 
177   TH1D    *g[outputNames.size()];
178   
179   for(int j=1; j<12; j++){ // not 13, last pad is empty (TODO)        
180     for(UInt_t i=0; i<outputNames.size(); i++){  
181            
182         ff[i] = TFile::Open(outputNames[i].Data());   
183         if(!ff[i] || ff[i]->IsZombie()){
184            printf("Non-existent, corrupted or zombie file %s\n", outputNames[i].Data());
185            return;
186         } 
187         ca[i]  = (TCanvas*)ff[i]->GetObjectUnchecked("can1");               
188         if(!ca[i]){
189            printf("Empty canvas in file %s.\n", outputNames[i].Data());
190            continue;
191         }       
192         pad[j] = (TPad*)ca[i]->GetListOfPrimitives()->FindObject(Form("can1_%d",j));            
193         if(!pad[j]){
194            printf("Empty pad in canvas %s.\n", ca[i]->GetName());
195            continue;         
196         }
197         g[i] =(TH1D*)pad[j]->FindObject(Form("fTrackHLT_proj_%d",j-1));
198         if(!g[i]){
199            printf("Empty histogram for i=%d, file %s.\n", i, outputNames[i].Data());
200            continue;
201         }
202         
203         ov->cd(j);      
204         if(i==0) g[i]->Draw();
205         else { 
206           g[i]->SetLineColor(i+1); 
207           defineYaxisMax(g[0], g[i]);
208           g[i]->Draw("sames");
209         }
210         ff[i]->Close();                                  
211     }
212   }  
213   file->Close();  
214 }
215
216 TString cutStudies( TCanvas* can1, TCanvas* can2, TCanvas* can3, TString folder,
217                     THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText,
218                     double minEta,   double maxEta,
219                     int minTrackMult,int maxTrackMult,
220                     double minPt,    double maxPt,
221                     double minDCAr,  double maxDCAr,
222                     double minDCAz,  double maxDCAz,
223                     int minTPCclus,  int maxTPCclus,
224                     int minITSclus,  int maxITSclus,
225                     int vertexStatus
226                   )
227 {
228   plotTrackQuantities(can1, htrackHLT, htrackOFF, hText, 
229                       minEta, maxEta, minPt, maxPt, minDCAr, maxDCAr, minDCAz, maxDCAz, minTPCclus, maxTPCclus, minITSclus, maxITSclus, minTrackMult, maxTrackMult, vertexStatus);
230   
231   plot2D(can2, htrackHLT, minEta, maxEta, minPt, maxPt, minDCAr, maxDCAr, minDCAz, maxDCAz, minTPCclus, maxTPCclus, minITSclus, maxITSclus, minTrackMult, maxTrackMult);
232   
233   plot2D(can3, htrackOFF, minEta, maxEta, minPt, maxPt, minDCAr, maxDCAr, minDCAz, maxDCAz, minTPCclus, maxTPCclus, minITSclus, maxITSclus, minTrackMult, maxTrackMult);
234   
235   TString cuts = cutsToString(minEta, maxEta, minPt, maxPt, minDCAr, maxDCAr, minDCAz, maxDCAz, minTPCclus, maxTPCclus, 
236                               minITSclus, maxITSclus, minTrackMult, maxTrackMult, vertexStatus);
237
238   can1->SaveAs(folder+"/track_properties_"+cuts+".root");
239   can1->SaveAs(folder+"/track_properties_"+cuts+".png");  
240   can2->SaveAs(folder+"/HLT_2D_track_correlations_"+cuts+".root");
241   can2->SaveAs(folder+"/HLT_2D_track_correlations_"+cuts+".png");
242   can3->SaveAs(folder+"/OFF_2D_track_correlations_"+cuts+".root");
243   can3->SaveAs(folder+"/OFF_2D_track_correlations_"+cuts+".png");
244   
245   return folder+"/track_properties_"+cuts+".root";
246 }
247
248 void printStats(TH1D *hlt, TH1D *off){  
249   gPad->Update();
250   TPaveStats *st1 = (TPaveStats*)hlt->FindObject("stats");
251   st1->SetLineColor(0);
252
253   gPad->Update();
254   TPaveStats *st2 = (TPaveStats*)off->FindObject("stats");
255   st2->SetY2NDC(st1->GetY1NDC()-0.05);
256   st2->SetY1NDC(st2->GetY2NDC()-TMath::Abs(st1->GetY1NDC()-st1->GetY2NDC()));
257   st2->SetLineColor(0);
258   st2->SetTextColor(off->GetLineColor());
259   st2->SetFillStyle(0);
260   st2->Draw();
261 }
262
263 void defineYaxisMax(TH1D *hlt, TH1D *off){ 
264   if(hlt->GetMaximum() > off->GetMaximum()) off->SetMaximum(1.1*hlt->GetMaximum());
265   else hlt->SetMaximum(1.1*off->GetMaximum());
266 }
267
268 void printLegend(TLegend *l, TH1D *hlt, TH1D *off){  
269   l->SetFillColor(10); 
270   l->SetLineColor(10);
271   l->AddEntry(hlt, "HLT", "l");
272   l->AddEntry(off, "OFF", "l");
273   l->Draw("same");
274 }
275
276 //====================== for 1D distributions ===============================//
277
278 void plotAid(TCanvas* can, THnSparse* hHLT, THnSparse* hOFF, TText* hText, TH1D *hlt, TH1D *off, TLegend *l, int size,
279              double minEta,    double maxEta,
280              double minPt,     double maxPt,
281              double minDCAr,   double maxDCAr,
282              double minDCAz,   double maxDCAz,
283              int minTPCclus,   int maxTPCclus,
284              int minITSclus,   int maxITSclus, 
285              int minTrackMult, int maxTrackMult,
286              int VS
287            )
288 {     
289    hHLT->GetAxis(0)->SetRangeUser(minPt,maxPt);
290    hHLT->GetAxis(1)->SetRangeUser(minTPCclus,maxTPCclus);
291    hHLT->GetAxis(3)->SetRangeUser(minEta, maxEta);
292    hHLT->GetAxis(5)->SetRangeUser(minDCAr, maxDCAr);
293    hHLT->GetAxis(6)->SetRangeUser(minDCAz, maxDCAz);
294    hHLT->GetAxis(10)->SetRangeUser(minITSclus, maxITSclus);
295    hHLT->GetAxis(11)->SetRangeUser(minTrackMult, maxTrackMult);
296    if(VS!=2) hHLT->GetAxis(12)->SetRangeUser(VS,VS);
297    
298    hOFF->GetAxis(0)->SetRangeUser(minPt,maxPt);
299    hOFF->GetAxis(1)->SetRangeUser(minTPCclus,maxTPCclus);
300    hOFF->GetAxis(3)->SetRangeUser(minEta, maxEta);
301    hOFF->GetAxis(5)->SetRangeUser(minDCAr, maxDCAr);
302    hOFF->GetAxis(6)->SetRangeUser(minDCAz, maxDCAz);
303    hOFF->GetAxis(10)->SetRangeUser(minITSclus, maxITSclus);
304    hOFF->GetAxis(11)->SetRangeUser(minTrackMult, maxTrackMult);
305    if(VS!=2) hOFF->GetAxis(12)->SetRangeUser(VS,VS);
306        
307    for(int i=0; i<size; i++){
308   
309       hlt = hHLT->Projection(i); if(!hlt){ printf("plotAid: empty HLT histogram\n"); continue; }
310       off = hOFF->Projection(i); if(!off){ printf("plotAid: empty OFF histogram\n"); continue; }
311       
312       hlt->SetTitle(fix1DTitle(hHLT->Projection(i)->GetTitle())); 
313    
314       TString s = hlt->GetTitle();      
315       if(s.Contains("p_")){ 
316          s+=" (GeV/c)";
317          hlt->SetXTitle(s);     
318       }
319       else if(s.Contains("theta") || s.Contains("phi")){
320          s+=" (rad)"; 
321          hlt->SetXTitle(s);
322       }
323       else if(s.Contains("DCA")){
324          s+=" (cm)";
325          hlt->SetXTitle(s);
326       }
327         
328       defineYaxisMax(hlt, off);
329       off->SetLineColor(2);
330     
331       can->cd(i+1);
332       hlt->Draw();
333       off->Draw("sames");
334       printStats(hlt, off);
335       
336       if(i==0){
337          printLegend(l,hlt,off);
338          TPaveText *pave = new TPaveText(25,5600,140,36400);
339          pave->SetFillColor(kWhite);
340          pave->SetLineColor(kWhite);
341          pave->SetShadowColor(kWhite);
342          TString s;              
343          s=""; s+=minEta; s+=" < eta < "; s+=maxEta; pave->AddText(s);
344          s=""; s+=minPt; s+=" < pt (GeV/c) < "; s+=maxPt; pave->AddText(s);
345          s=""; s+=minTrackMult; s+=" < track mult < "; s+=maxTrackMult; pave->AddText(s);
346          s=""; s+=minDCAr; s+=" < DCAr (cm) < "; s+=maxDCAr; pave->AddText(s);
347          s=""; s+=minDCAz; s+=" < DCAz (cm) < "; s+=maxDCAz; pave->AddText(s);
348          s=""; s+=minTPCclus; s+=" < TPC clusters/track < "; s+=maxTPCclus; pave->AddText(s);
349          s=""; s+=minITSclus; s+=" < ITS clusters/track < "; s+=maxITSclus; pave->AddText(s);
350          if(VS!=2) { s=""; s+="vertex status "; s+=VS; pave->AddText(s); }
351          pave->Draw();
352          can->Update();
353       }      
354    } 
355 }
356
357 //====================== for 2D distributions ===============================//
358
359 void plot2D(TCanvas* can, THnSparse* h,
360             double minEta,    double maxEta,
361             double minPt,     double maxPt,
362             double minDCAr,   double maxDCAr,
363             double minDCAz,   double maxDCAz,
364             int minTPCclus,   int maxTPCclus,
365             int minITSclus,   int maxITSclus, 
366             int minTrackMult, int maxTrackMult
367            )
368 {
369   h->GetAxis(0)->SetRangeUser(minPt,maxPt);
370   h->GetAxis(1)->SetRangeUser(minTPCclus,maxTPCclus);
371   h->GetAxis(3)->SetRangeUser(minEta, maxEta);
372   h->GetAxis(5)->SetRangeUser(minDCAr, maxDCAr);
373   h->GetAxis(6)->SetRangeUser(minDCAz, maxDCAz);
374   h->GetAxis(10)->SetRangeUser(minITSclus, maxITSclus);
375   h->GetAxis(11)->SetRangeUser(minTrackMult, maxTrackMult);
376   
377   can->cd(1);    
378   TH2D *ht = h->Projection(1,0);
379   ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(0)->GetTitle()));
380
381   TString s = "";
382   s = fix1DTitle(h->Projection(0)->GetTitle())+" (GeV/c)";
383   ht->SetXTitle(s);
384   ht->Draw("colz");
385   
386   can->cd(2);
387   ht = h->Projection(1,3);
388   ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(3)->GetTitle()));
389   ht->Draw("colz");
390   
391   can->cd(3);
392   ht = h->Projection(1,5);
393   ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(5)->GetTitle()));
394   s = fix1DTitle(h->Projection(5)->GetTitle())+" (cm)";
395   ht->SetXTitle(s);
396   ht->Draw("colz");
397   
398   can->cd(4);
399   ht = h->Projection(1,6);
400   ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(6)->GetTitle()));
401   s = fix1DTitle(h->Projection(6)->GetTitle())+" (cm)";
402   ht->SetXTitle(s);
403   ht->Draw("colz");
404   
405   can->cd(5);
406   ht = h->Projection(6,0);
407   ht->SetTitle(fix2DTitle(h->Projection(6)->GetTitle(), h->Projection(0)->GetTitle()));
408   s = fix1DTitle(h->Projection(0)->GetTitle())+" (GeV/c)";
409   ht->SetXTitle(s);
410   s = fix1DTitle(h->Projection(6)->GetTitle())+" (cm)";
411   ht->SetYTitle(s);
412   ht->Draw("colz");
413   
414   can->cd(6);
415   ht = h->Projection(6,3);
416   ht->SetTitle(fix2DTitle(h->Projection(6)->GetTitle(), h->Projection(3)->GetTitle()));
417   s = fix1DTitle(h->Projection(6)->GetTitle())+" (cm)";
418   ht->SetYTitle(s);
419   ht->Draw("colz");
420   
421   can->cd(7);
422   ht = h->Projection(3,0);
423   ht->SetTitle(fix2DTitle(h->Projection(3)->GetTitle(), h->Projection(0)->GetTitle()));
424   s = fix1DTitle(h->Projection(0)->GetTitle())+" (GeV/c)";
425   ht->SetXTitle(s);
426   ht->Draw("colz");
427   
428   can->cd(8);
429   ht = h->Projection(3,4);
430   ht->SetTitle(fix2DTitle(h->Projection(3)->GetTitle(), h->Projection(4)->GetTitle()));
431   s = fix1DTitle(h->Projection(4)->GetTitle())+" (rad)";
432   ht->SetXTitle(s);
433   ht->Draw("colz"); 
434 }
435
436 void plotAid(TCanvas* can, THnSparse* hHLT, THnSparse* hOFF, TText* hText, TH1D *hlt, TH1D *off, TLegend *l, int size){
437  
438   for(int i=0; i<size; i++){         
439       hlt = hHLT->Projection(i);
440       off = hOFF->Projection(i); 
441       hlt->SetTitle(fix1DTitle(hHLT->Projection(i)->GetTitle()));      
442       TString s = hlt->GetTitle();      
443       if(s.Contains("primary")){ 
444          s+=" (cm)";
445          hlt->SetXTitle(s);     
446       }
447      
448       defineYaxisMax(hlt, off);
449       off->SetLineColor(2);
450      
451       can->cd(i+1);
452       hlt->Draw();
453       off->Draw("sames");
454       printStats(hlt, off);
455       
456       if(i==0) printLegend(l,hlt,off);
457    } 
458 }
459
460 void plotEventQuantities(TCanvas* can, THnSparse* heventHLT, THnSparse* heventOFF, TText* hText){
461
462   TH1D *hlt = NULL;
463   TH1D *off = NULL;
464  
465   TLegend *leg1 = new TLegend(0.6,0.6,0.8,0.8);
466  
467   plotAid(can, heventHLT, heventOFF, hText, hlt, off, leg1, 6);  
468   return;
469 }
470
471 void plotTrackQuantities( TCanvas* can, THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText,
472                           double minEta,    double maxEta,
473                           double minPt,     double maxPt,
474                           double minDCAr,   double maxDCAr,
475                           double minDCAz,   double maxDCAz,
476                           int minTPCclus,   int maxTPCclus,
477                           int minITSclus,   int maxITSclus, 
478                           int minTrackMult, int maxTrackMult,
479                           int VS
480                         )
481 {
482   TH1D *hlt = NULL;
483   TH1D *off = NULL;
484  
485   TLegend *leg1 = new TLegend(0.6,0.6,0.8,0.8);
486   plotAid(can, htrackHLT, htrackOFF, hText, hlt, off, leg1, 11, 
487           minEta, maxEta, minPt, maxPt, minDCAr, maxDCAr, minDCAz, maxDCAz, minTPCclus, maxTPCclus, minITSclus, maxITSclus, minTrackMult, maxTrackMult, VS);  
488   return;
489 }
490
491 TString fix1DTitle(const char* c){
492   TString tmp = c;
493   tmp.ReplaceAll("projection ","");
494   return tmp;   
495 }
496
497 TString fix2DTitle(const char* c1, const char* c2){
498   TString tmp = fix1DTitle(c1)+" vs."+fix1DTitle(c2);
499   return tmp;
500 }
501
502 TString cutsToString( double minEta,    double maxEta,
503                       double minPt,     double maxPt,
504                       double minDCAr,   double maxDCAr,
505                       double minDCAz,   double maxDCAz,
506                       int minTPCclus,   int maxTPCclus,
507                       int minITSclus,   int maxITSclus, 
508                       int minTrackMult, int maxTrackMult,
509                       int VS
510                     )
511 {
512   TString cuts = "";
513   char s[300]; sprintf(s, "eta%2g_%2g_Pt%2g_%2g_TM%d_%d_DCAr%2g_%2g_DCAz%2g_%2g_TPCclus%d_%d_ITSclus%d_%d", 
514                            minEta,maxEta,minPt,maxPt,minTrackMult,maxTrackMult,minDCAr,maxDCAr,minDCAz,maxDCAz,minTPCclus,maxTPCclus,minITSclus,maxITSclus);
515   cuts = s; cuts.ReplaceAll(" ","");
516  
517   if(VS!=2){
518     char v[10]; 
519     sprintf(v, "_VS%d",VS);
520     cuts+=v;
521   }
522   return cuts;
523 }