removed startTime selection
[u/mrichter/AliRoot.git] / ANALYSIS / macros / QAtrain.C
1 #include "Riostream.h"
2 void LoadLibraries();
3 void AddAnalysisTasks(); 
4 void QAmerge(const char *, Int_t);
5
6 Int_t iCollisionType = 0; // 0=pp, 1=PbPb
7 // Trigger mask.
8
9 UInt_t kTriggerInt = AliVEvent::kAnyINT;
10 UInt_t kTriggerMuonBarell = AliVEvent::kMUU7;
11 UInt_t kTriggerEMC   = AliVEvent::kEMC7 | AliVEvent::kEMCEJE | AliVEvent::kEMCEGA;
12 UInt_t kTriggerHM   = AliVEvent::kHighMult;
13 // Main trigger mask used:
14 UInt_t kTriggerMask = kTriggerInt;
15
16 Int_t runNumbers[5] = {158626};
17
18 Bool_t doCDBconnect   = 1;
19 Bool_t doEventStat    = 1;
20 Bool_t doCentrality   = 1;
21 Bool_t doQAsym        = 1;
22 Bool_t doVZERO        = 1;   // there is a 2nd file
23 Bool_t doVZEROPbPb    = 0; 
24 Bool_t doVertex       = 1;
25 Bool_t doSPD          = 1;   // needs RP   
26 Bool_t doTPC          = 1;
27 Bool_t doHLT          = 1;
28 Bool_t doSDD          = 1;   // needs RP
29 Bool_t doSSDdEdx      = 1;
30
31 Bool_t doTRD          = 1;
32 Bool_t doITS          = 1;
33 Bool_t doITSsaTracks  = 1; 
34 Bool_t doITSalign     = 1;  
35 Bool_t doCALO         = 1;
36 Bool_t doMUONTrig     = 1;
37 Bool_t doImpParRes    = 1;
38 Bool_t doMUON         = 1;
39 Bool_t doTOF          = 1;
40 Bool_t doHMPID        = 1;
41 Bool_t doT0           = 1;
42 Bool_t doZDC          = 1;
43 Bool_t doPIDResponse  = 1;
44 Bool_t doPIDqa        = 1; //new
45 Bool_t doFMD          = 1; // new
46 Bool_t doPHOS         = 1; // new
47 Bool_t doEMCAL        = 1;
48 Bool_t doFBFqa        = 1; // new - not ported yet to revision
49
50                // Debug level
51 Int_t       debug_level        = 1;        // Debugging
52 Int_t       run_number = 0;
53
54 void QAtrain(Int_t run = 0, 
55              const char *xmlfile   = "wn.xml",
56              Int_t  stage          = 0) /*0 = QA train, 1...n - merging stage*/
57 {
58   run_number = run;
59
60   TGrid::Connect("alien://");
61   if (!gGrid || !gGrid->IsConnected()) {
62     ::Error("QAtrain", "No grid connection");
63     return;
64   }   
65   // Set temporary merging directory to current one
66   gSystem->Setenv("TMPDIR", gSystem->pwd());
67   // Set temporary compilation directory to current one
68   gSystem->SetBuildDir(gSystem->pwd(), kTRUE);
69   // Load libraries
70   LoadLibraries();
71   printf("Include path: %s\n", gSystem->GetIncludePath());
72   // Create manager
73   AliAnalysisManager *mgr  = new AliAnalysisManager("PilotAnalysis", "Production train");
74   mgr->SetRunFromPath(run_number);
75   // Input handler
76   AliESDInputHandlerRP *esdHandler = new AliESDInputHandlerRP();
77   esdHandler->SetReadFriends(kTRUE);
78   esdHandler->SetActiveBranches("ESDfriend");
79   mgr->SetInputEventHandler(esdHandler);
80   mgr->SetDebugLevel(debug_level);
81   
82   // AnalysisTasks
83   AddAnalysisTasks();
84   if (stage>0) {
85     QAmerge(xmlfile, stage);
86     return;
87   }   
88   // Input chain
89   TChain *chain = new TChain("esdTree");
90   chain->Add("AliESDs.root");
91   TStopwatch timer;
92   timer.Start();
93   if (mgr->InitAnalysis()) {                                                                                                              
94     mgr->PrintStatus(); 
95     mgr->SetSkipTerminate(kTRUE);
96 //    mgr->SetNSysInfo(1);
97     mgr->StartAnalysis("local", chain);
98   }
99   timer.Print();
100 }
101
102 void LoadLibraries()
103 {
104   gSystem->SetIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT/include -I$ALICE_ROOT -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TRD -I$ALICE_ROOT/PWGPP -I$ALICE_ROOT/PWGPP/TRD");
105   gSystem->Load("libANALYSIS");
106   gSystem->Load("libANALYSISalice");
107   gSystem->Load("libCORRFW");
108   gSystem->Load("libTENDER");
109   gSystem->Load("libPWGPP.so");
110   gSystem->Load("libAliHLTTrigger.so");
111
112   if (doEMCAL || doPHOS || doCALO) {
113      gSystem->Load("libEMCALUtils");
114      gSystem->Load("libPHOSUtils");
115      gSystem->Load("libPWGCaloTrackCorrBase");
116      gSystem->Load("libPWGGACaloTrackCorrelations");
117      gSystem->Load("libPWGGACaloTasks");
118      gSystem->Load("libPWGGAPHOSTasks");
119      gSystem->Load("libPWGGAEMCALTasks");
120   }  
121   if(doMUON || doMUONTrig) {
122      gSystem->Load("libPWGmuon");
123      gSystem->Load("libPWGPPMUONlite");
124      gSystem->Load("libPWGmuondep");
125   }
126   if (doFMD) {
127      gSystem->Load("libPWGLFforward2");
128   }      
129 }
130
131 void AddAnalysisTasks()
132 {
133   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
134   mgr->SetCommonFileName("QAresults.root");
135   // Statistics task
136   mgr->AddStatisticsTask(kTriggerMask);
137   //
138   // CDB connection
139   //
140   if (doCDBconnect) {
141     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskCDBconnect.C");
142     AliTaskCDBconnect *taskCDB = AddTaskCDBconnect();
143     if (!taskCDB) return;
144     AliCDBManager *cdb = AliCDBManager::Instance();
145     cdb->SetDefaultStorage("raw://");
146     taskCDB->SetRunNumber(run_number);
147   }    
148   
149   //
150   // Event Statistics (Jan Fiete)
151   //
152   if (doEventStat) {
153       gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
154       AliPhysicsSelectionTask* physSelTask = AddTaskPhysicsSelection(kFALSE /*MC*/);
155   }
156   
157   //
158   // Centrality (A. Toia)
159   //
160   if (doCentrality) {
161      if (!iCollisionType) {
162         printf("Disabling centrality task for p-p\n");
163         doCentrality = kFALSE;
164      } else {           
165         gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskCentrality.C");
166         AliCentralitySelectionTask *taskCentrality = AddTaskCentrality();
167      }   
168   }   
169   
170   // Vertexing (A. Dainese)
171   // 
172   if (doVertex) {
173     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskVertexESD.C");
174     AliAnalysisTaskVertexESD* taskvertexesd =  AddTaskVertexESD(kFALSE, kTriggerMask);
175     taskvertexesd->SelectCollisionCandidates(kTriggerMask);
176   }  
177
178   // TPC QA (E. Sicking)
179   //
180   if (doQAsym) {
181   // offline trigger in AddTask
182     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskQAsym.C");
183     AliAnalysisTaskSE * taskqasim = AddTaskQAsym(0, kTriggerMask, kTriggerHM, kTriggerEMC, kTriggerMuonBarell);
184   }  
185   //
186   // VZERO QA  (C. Cheshkov)
187   //
188   if (doVZERO) {
189     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskVZEROQA.C");
190     AliAnalysisTaskSE * taskv0qa = AddTaskVZEROQA(0);
191 //  taskv0qa->SelectCollisionCandidates();
192   }
193   if (doVZEROPbPb && iCollisionType==1) {
194     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/VZERO/AddTaskVZEROPbPb.C");
195     AliAnaVZEROPbPb* taskV0PbPb = (AliAnaVZEROPbPb*)AddTaskVZEROPbPb(0);
196     taskV0PbPb->SetClassesNames("CTRUE-,C0HWU-,CPBI2WU-,CPBI2-,CPBI2WU_B1-,CPBI2_B1-,CPBI1WU-,CPBI1-,CVHNWU-,CVHN-,CVHN_R2-,CVHNWU_R2-,CVLNWU-,CVLN-,CVLN_R1-,CVLN_B2-,CVLNWU_R1-,CVLNWU_B2-,CSEMI_R1-,CSEMIWU_R1-,CCENT_R2-,CCENTWU_R2-");
197   }
198   //
199   // TPC (Jacek Otwinowski & Michael Knichel)
200   //
201   //
202   // Optionally MC information can be used by setting the 1st argument to true
203   // Optionally friends information can be switched off by setting the 2st argument 
204   // to false
205   // Optionally highMult axis can be used by setting the 3st argument to true (for PbPb)
206   if (doTPC) {
207     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/TPC/macros/AddTaskPerformanceTPCdEdxQA.C");
208     AliPerformanceTask *tpcQA = 0;
209     if (iCollisionType) {
210        // High multiplicity Pb-Pb
211        tpcQA = AddTaskPerformanceTPCdEdxQA(kFALSE, kTRUE, kTRUE);
212     } else {
213       // Low multiplicity (pp)
214        tpcQA = AddTaskPerformanceTPCdEdxQA(kFALSE, kTRUE, kFALSE);
215     }
216     tpcQA->SelectCollisionCandidates(kTriggerMask);
217   }  
218
219   // HLT (Alberica Toia)
220   if (doHLT) {
221     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/TPC/macros/AddTaskPerformanceTPCdEdxQA.C");
222     AliPerformanceTask *hltQA = AddTaskPerformanceTPCdEdxQA(kFALSE, kTRUE, kFALSE,0,kTRUE);
223     hltQA->SelectCollisionCandidates(kTriggerMask);
224   }  
225   //
226   // SPD (A. Mastroserio)
227   //
228   if (doSPD) {
229     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskSPDQA.C");
230     AliAnalysisTaskSPD* taskspdqa = (AliAnalysisTaskSPD*)AddTaskSPDQA();
231     // Request from Annalisa
232     if (iCollisionType) taskspdqa->SetHeavyIonMode();
233     taskspdqa->SelectCollisionCandidates(kTriggerMask);
234     taskspdqa->SetOCDBInfo(run_number, "raw://");
235   }  
236   //
237   // SDD (F. Prino)
238   //
239   if (doSDD) {
240     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddSDDPoints.C");
241     AliAnalysisTaskSE* tasksdd = AddSDDPoints();
242     tasksdd->SelectCollisionCandidates(kTriggerMask);
243   }
244   //
245   // SSD dEdx (Marek Chojnacki)
246   //
247   if (doSSDdEdx) {
248     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskdEdxSSDQA.C");
249     AliAnalysisTaskSE* taskssddedx = AddTaskdEdxSSDQA();
250     taskssddedx->SelectCollisionCandidates(kTriggerMask);
251   }
252
253   //
254   // ITS
255   //
256   if (doITS) {
257   // hardcoded non-zero trigger mask
258       gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskPerformanceITS.C");
259       AliAnalysisTaskITSTrackingCheck *itsQA = 0;
260       AliAnalysisTaskITSTrackingCheck *itsQACent0010 = 0;
261       AliAnalysisTaskITSTrackingCheck *itsQACent3050 = 0;
262       AliAnalysisTaskITSTrackingCheck *itsQACent6080 = 0;
263       if(iCollisionType==0) {
264         itsQA = AddTaskPerformanceITS(kFALSE);
265       } else {
266         itsQA = AddTaskPerformanceITS(kFALSE);
267         itsQACent0010 = AddTaskPerformanceITS(kFALSE,kFALSE,kFALSE,3500,10000);
268         itsQACent3050 = AddTaskPerformanceITS(kFALSE,kFALSE,kFALSE,590,1570);
269         itsQACent6080 = AddTaskPerformanceITS(kFALSE,kFALSE,kFALSE,70,310);
270       }
271   }
272   //
273   // ITS saTracks, align (F.Prino)
274   //
275   if (doITSsaTracks) {
276   // offline trigger in AddTask
277      gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskITSsaTracks.C");
278      AliAnalysisTaskITSsaTracks *itssaTracks = AddTaskITSsaTracks(kFALSE,kFALSE);
279      itssaTracks->SelectCollisionCandidates(kTriggerMask);
280   }   
281   if (doITSalign) {
282   // no offline trigger selection
283      gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskITSAlign.C");
284      AliAnalysisTaskITSAlignQA *itsAlign = AddTaskITSAlign(0,2011);
285   }   
286   //
287   // TRD (Alex Bercuci, M. Fasel) 
288   //
289   if(doTRD) {
290   // no offline trigger selection
291       gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTrainPerformanceTRD.C");
292       // steer individual TRD tasks
293       Bool_t 
294       doCheckESD(kTRUE),  // AliTRDcheckESD
295       doCheckDET(kTRUE),  // AliTRDcheckDET
296       doEffic(kTRUE),     // AliTRDefficiency
297       doResolution(kTRUE),// AliTRDresolution
298       doCheckPID(kTRUE),  // AliTRDcheckPID
299       doV0Monitor(kFALSE);// AliTRDv0Monitor
300       AddTrainPerformanceTRD(Translate(doCheckESD, doCheckDET, doEffic, doResolution, doCheckPID, doV0Monitor));
301   }
302
303   //
304   // ZDC (Chiara Oppedisano) 
305   //
306   if(doZDC) {
307   // hardcoded kMB trigger mask
308      gROOT->LoadMacro("$ALICE_ROOT/PWGPP/ZDC/AddTaskZDCQA.C");
309      AliAnalysisTaskSE *taskZDC = AddTaskZDCQA();
310      taskZDC->SelectCollisionCandidates(kTriggerMask);
311   }   
312   //
313   // Calorimetry (Gustavo Conesa)
314   //
315
316   if(doCALO) {
317       gROOT->LoadMacro("$ALICE_ROOT/PWGGA/CaloTrackCorrelations/macros/QA/AddTaskCalorimeterQA.C");
318       AliAnalysisTaskCaloTrackCorrelation *taskCaloQA = AddTaskCalorimeterQA("ESD", 2011, kFALSE, kFALSE);
319       taskCaloQA->SetDebugLevel(0);
320       // offline mask set in AddTask to kMB
321       taskCaloQA->SelectCollisionCandidates(kTriggerMask);
322       // Add a new calo task with EMC1 trigger only
323       taskCaloQA = AddTaskCalorimeterQA("ESD", 2011, kFALSE, kFALSE, "", "EMC7");
324       taskCaloQA->SetDebugLevel(0);
325       taskCaloQA->SelectCollisionCandidates(kTriggerEMC);
326   }
327
328   //
329   // Muon Trigger
330   //
331   
332   if(doMUONTrig) {
333   // no offline trigger selection
334       gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskMTRchamberEfficiency.C");
335       AliAnalysisTaskTrigChEff *taskMuonTrig = AddTaskMTRchamberEfficiency();
336   }
337
338   //
339   // Impact parameter resolution (xianbao.yuan@pd.infn.it, andrea.dainese@pd.infn.it)
340   //
341   if (doImpParRes) {
342     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskImpParRes.C");
343     AliAnalysisTaskSE* taskimpparres=0;
344     if(iCollisionType==0) {
345        taskimpparres= AddTaskImpParRes();
346     } else {
347        taskimpparres= AddTaskImpParRes(kFALSE,-1,kFALSE,kFALSE);
348     }
349     taskimpparres->SelectCollisionCandidates(kTriggerMask);
350   }  
351   //
352   // MUON QA (Philippe Pillot)
353   //
354   if (doMUON) {
355   // trigger analysis internal
356     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/PilotTrain/AddTaskMuonQA.C");
357     AliAnalysisTaskSE* taskmuonqa= AddTaskMuonQA();
358   }  
359   //
360   // TOF (Francesca Bellini)
361   //
362   if (doTOF) {
363     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/TOF/AddTaskTOFQA.C");
364     AliAnalysisTaskTOFqa *tofQA = AddTaskTOFQA();
365     tofQA->SelectCollisionCandidates(kTriggerMask);
366   } 
367    //
368   // PIDResponse(JENS)
369   //
370   if (doPIDResponse) {
371     gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPIDResponse.C"); 
372     AliAnalysisTaskPIDResponse *PIDResponse = AddTaskPIDResponse();
373     PIDResponse->SelectCollisionCandidates(kTriggerMask);
374   }  
375
376   //
377   // PIDqa(JENS)
378   //
379   if (doPIDqa) {
380     gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPIDqa.C");
381     AliAnalysisTaskPIDqa *PIDQA = AddTaskPIDqa();
382     PIDQA->SelectCollisionCandidates(kTriggerMask);
383   }  
384  
385   //
386   // HMPID QA (Giacomo Volpe)
387   //
388   if (doHMPID) {
389     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/HMPID/AddTaskHmpidQA.C");
390     AliAnalysisTaskSE* taskhmpidqa= AddTaskHmpidQA(kFALSE);
391       // offline mask set in AddTask to kMB
392     taskhmpidqa->SelectCollisionCandidates(kTriggerMask);
393   }      
394   
395   
396   // T0 QA (Alla Mayevskaya)
397   if (doT0) {
398   // no offline trigger selection
399     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/T0/AddTaskT0QA.C");
400     AliT0AnalysisTaskQA* taskt0qa= AddTaskT0QA();
401     taskt0qa->SelectCollisionCandidates(kTriggerMask);
402   }      
403   // FMD QA (Christian Holm Christiansen)
404   if (doFMD) {
405     gROOT->LoadMacro("$ALICE_ROOT/PWGLF/FORWARD/analysis2/AddTaskForwardQA.C");
406     // Parameters: usemc, usecentrality
407     AliAnalysisTaskSE *forwardQA = (AliAnalysisTaskSE *)AddTaskForwardQA(kFALSE, kFALSE);
408     // No offline trigger config. needed (see #84077)
409   }
410    //     
411   // PHOS QA (Boris Polishchuk)
412   //
413   if (doPHOS) {
414     gROOT->LoadMacro("$ALICE_ROOT/PWGGA/PHOSTasks/CaloCellQA/macros/AddTaskCaloCellsQA.C");
415     AliAnalysisTaskCaloCellsQA *taskPHOSCellQA1 = AddTaskCaloCellsQA(4, 1, NULL,"PHOSCellsQA_AnyInt"); 
416     taskPHOSCellQA1->SelectCollisionCandidates(kTriggerMask);
417     taskPHOSCellQA1->GetCaloCellsQA()->SetClusterEnergyCuts(0.3,0.3,1.0);
418     AliAnalysisTaskCaloCellsQA *taskPHOSCellQA2 = AddTaskCaloCellsQA(4, 1, NULL,"PHOSCellsQA_PHI7"); 
419     taskPHOSCellQA2->SelectCollisionCandidates(AliVEvent::kPHI7);
420     taskPHOSCellQA2->GetCaloCellsQA()->SetClusterEnergyCuts(0.3,0.3,1.0);
421     // Pi0 QA fo PbPb
422     if (iCollisionType) {
423       gROOT->LoadMacro("$ALICE_ROOT/PWGGA/PHOSTasks/PHOS_PbPbQA/macros/AddTaskPHOSPbPb.C");
424       AliAnalysisTaskPHOSPbPbQA* phosPbPb = AddTaskPHOSPbPbQA(0);
425     }
426   }    
427   //
428   // EMCAL QA (Gustavo Conesa)
429   //
430   if (doEMCAL) {
431      gROOT->LoadMacro("$ALICE_ROOT/PWGGA/EMCALTasks/macros/AddTaskEMCALTriggerQA.C");
432      AliAnalysisTaskEMCALTriggerQA *emctrig = AddTaskEMCALTriggerQA();
433   }   
434   //     
435   // FLOW and BF QA (C.Perez && A.Rodriguez)
436   //
437   if (doFBFqa) {
438     gROOT->LoadMacro("$ALICE_ROOT/PWGPP/macros/AddTaskFBFqa.C");
439     AliAnalysisTaskSE *qaFBFMB = (AliAnalysisTaskSE*) AddTaskFBFqa("qaFBFmb",kFALSE);
440     qaFBFMB->SelectCollisionCandidates(AliVEvent::kMB);
441     AliAnalysisTaskSE *qaFBFSC = (AliAnalysisTaskSE*) AddTaskFBFqa("qaFBFsc",kFALSE);
442     qaFBFSC->SelectCollisionCandidates(AliVEvent::kSemiCentral);
443     AliAnalysisTaskSE *qaFBFCE = (AliAnalysisTaskSE*) AddTaskFBFqa("qaFBFce",kFALSE);
444     qaFBFCE->SelectCollisionCandidates(AliVEvent::kCentral);
445   }
446 }
447
448 void QAmerge(const char *dir, Int_t stage)
449 {
450 // Merging method
451   TStopwatch timer;
452   timer.Start();
453   TString outputDir = dir;
454   TString outputFiles = "QAresults.root,EventStat_temp.root,RecoQAresults.root";
455   TString mergeExcludes = "";
456   TObjArray *list = outputFiles.Tokenize(",");
457   TIter *iter = new TIter(list);
458   TObjString *str;
459   TString outputFile;
460   Bool_t merged = kTRUE;
461   while((str=(TObjString*)iter->Next())) {
462     outputFile = str->GetString();
463     // Skip already merged outputs
464     if (!gSystem->AccessPathName(outputFile)) {
465        printf("Output file <%s> found. Not merging again.",outputFile.Data());
466        continue;
467     }
468     if (mergeExcludes.Contains(outputFile.Data())) continue;
469     merged = AliAnalysisAlien::MergeOutput(outputFile, outputDir, 10, stage);
470     if (!merged && outputFile!="RecoQAresults.root") {
471        printf("ERROR: Cannot merge %s\n", outputFile.Data());
472        return;
473     }
474   }
475   // read the analysis manager from file
476   if (!outputDir.Contains("Stage")) {
477     ofstream out;
478     out.open("outputs_valid", ios::out);
479     out.close();    
480     return;
481   }
482   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
483   mgr->SetRunFromPath(mgr->GetRunFromAlienPath(dir));
484   mgr->SetSkipTerminate(kFALSE);
485   if (!mgr->InitAnalysis()) return;
486   mgr->PrintStatus();
487   AliLog::SetGlobalLogLevel(AliLog::kError);
488   TTree *tree = NULL;
489   mgr->StartAnalysis("gridterminate", tree);
490   ofstream out;
491   out.open("outputs_valid", ios::out);
492   out.close();
493   timer.Print();
494 }