Adding a tool to mchview to compare alignments (Philippe P. ; Laurent)
[u/mrichter/AliRoot.git] / MUON / AliMUONMchViewApplication.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17
18 #include "AliMUONMchViewApplication.h"
19
20 #include "AliCDBManager.h"
21 #include "AliCodeTimer.h"
22 #include "AliLog.h"
23 #include "AliMUONAlignmentCompareDialog.h"
24 #include "AliMUONChamberPainter.h"
25 #include "AliMUONDEPainter.h"
26 #include "AliMUONPainterDataRegistry.h"
27 #include "AliMUONPainterDataSourceFrame.h"
28 #include "AliMUONPainterEnv.h"
29 #include "AliMUONPainterHelper.h"
30 #include "AliMUONPainterGroup.h"
31 #include "AliMUONPainterMasterFrame.h"
32 #include "AliMUONPainterMatrix.h"
33 #include "AliMUONPainterRegistry.h"
34 #include "AliMUONTrackerDataCompareDialog.h"
35 #include "AliMUONTrackerDataWrapper.h"
36 #include "AliMUONVTrackerData.h"
37 #include "AliMUONVTrackerDataMaker.h"
38 #include <Riostream.h>
39 #include <TCanvas.h>
40 #include <TEnv.h>
41 #include <TFile.h>
42 #include <TGClient.h>
43 #include <TGFileDialog.h>
44 #include <TGMenu.h>
45 #include <TGTab.h>
46 #include <TGTextView.h>
47 #include <TGrid.h>
48 #include <TKey.h>
49 #include <TList.h>
50 #include <TRegexp.h>
51 #include <TString.h>
52 #include <TSystem.h>
53
54 /// \class AliMUONMchViewApplication
55 ///
56 /// Main class for the mchview program
57 ///
58 ///\author Laurent Aphecetche, Subatech
59
60 /// \cond CLASSIMP
61 ClassImp(AliMUONMchViewApplication)
62 /// \endcond CLASSIMP
63
64 const Int_t AliMUONMchViewApplication::fgkFILESAVEAS(1);
65 const Int_t AliMUONMchViewApplication::fgkFILEOPEN(2);
66 const Int_t AliMUONMchViewApplication::fgkFILEEXIT(3);
67 const Int_t AliMUONMchViewApplication::fgkFILEPRINTAS(4);
68 const Int_t AliMUONMchViewApplication::fgkABOUT(5);
69 const Int_t AliMUONMchViewApplication::fgkCOMPAREDATA(6);
70 const Int_t AliMUONMchViewApplication::fgkCOMPAREALIGNMENTS(7);
71
72 const char* AliMUONMchViewApplication::fgkFileTypes[] = { 
73   "ROOT files",    "*.root", 
74   "All files",     "*", 
75   0,               0 }; 
76
77 //______________________________________________________________________________
78 AliMUONMchViewApplication::AliMUONMchViewApplication(const char* name,
79                                                      int* argc, char** argv,
80                                                      UInt_t w, UInt_t h,
81                                                      UInt_t ox, UInt_t oy) 
82 : TRint(name,argc,argv),
83   fMainFrame(0x0),
84   fPainterMasterFrameList(new TList),
85   fTabs(0x0)
86 {
87
88   /// ctor
89   /// (w,h) is the size in pixel (if 0,0 it will be computed as 70%,90% of display size)
90   /// (ox,oy) is the offset from the top-left of the display
91
92   if (!w || !h)
93   {
94     w = (UInt_t)(gClient->GetDisplayWidth()*0.7);
95     h = (UInt_t)(gClient->GetDisplayHeight()*0.9); 
96   }
97
98   fMainFrame = new TGMainFrame(gClient->GetRoot(),w,h);
99
100   CreateMenuBar(w);
101
102   const Int_t kbs = 2;
103   
104 //  h -= 60; // menubar
105   
106   fTabs = new TGTab(fMainFrame,w,h);
107   
108   TGCompositeFrame* t = fTabs->AddTab("Painter Master Frame");
109
110   fPainterMasterFrameList->SetOwner(kTRUE);
111   
112   
113   AliMUONPainterMasterFrame* pmf = new AliMUONPainterMasterFrame(t,t->GetWidth()-kbs*2,t->GetHeight()-kbs*2,
114                                                                  GenerateStartupMatrix());
115
116   fPainterMasterFrameList->Add(pmf);
117   
118   t->AddFrame(pmf, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,kbs,kbs,kbs,kbs));
119
120   t = fTabs->AddTab("Data Sources");
121   
122   AliMUONPainterDataSourceFrame* dsf = 
123     new AliMUONPainterDataSourceFrame(t,t->GetWidth()-kbs*2,t->GetHeight()-kbs*2);
124   
125   t->AddFrame(dsf,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,kbs,kbs,kbs,kbs));
126   
127   fMainFrame->AddFrame(fTabs,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY,0,0,0,0));
128
129   fMainFrame->SetWindowName("mchview - Visualization of MUON Tracker detector");
130
131   fMainFrame->MapSubwindows();
132   fMainFrame->Resize();
133   
134   pmf->Update();
135   
136   fMainFrame->MapWindow();
137   
138   fMainFrame->Connect("CloseWindow()","AliMUONMchViewApplication",this,"Terminate()");
139
140 //  fMainFrame->MoveResize(ox,oy, w, h); 
141   fMainFrame->SetWMPosition(ox, oy);
142 //  fMainFrame->SetWMSizeHints(w,h,w,h,0,0);
143 //  fMainFrame->SetWMSizeHints(w,h,w,h,10,10);
144   
145   cout << "***************************************************" << endl;
146   cout << "   Welcome to mchview" << endl;
147   cout << "   " << FullVersion() << endl;
148   cout << "***************************************************" << endl;
149   
150   // Trying to see if we're requested to draw something specific instead
151   // of the global view of all the chambers
152   
153   AliMUONVPainter* painter(0x0);
154   TObjArray args;
155   args.SetOwner(kTRUE);
156   
157   for ( int i = 1; i < argc[0]; ++i ) 
158   {
159     args.Add(new TObjString(argv[i]));
160   }
161   
162   for ( Int_t i = 0; i <= args.GetLast(); ++i ) 
163   {
164     TString a(static_cast<TObjString*>(args.At(i))->String());
165
166     AliMUONAttPainter att;
167     
168     att.SetPlane(kTRUE,kFALSE);
169     att.SetCathode(kFALSE,kFALSE);
170     att.SetViewPoint(kTRUE,kFALSE);
171         
172     if ( a == "--de" )
173     {
174       Int_t detElemId = static_cast<TObjString*>(args.At(i+1))->String().Atoi();
175       
176       painter = new AliMUONDEPainter(att,detElemId);
177       
178       painter->SetOutlined("*",kFALSE);      
179       painter->SetOutlined("BUSPATCH",kTRUE);
180
181       painter->SetLine(1,4,3);      
182       ++i;
183     }
184
185     if ( a == "--chamber" )
186     {
187       Int_t chamberId = static_cast<TObjString*>(args.At(i+1))->String().Atoi();
188       
189       painter = new AliMUONChamberPainter(att,chamberId-1);
190       
191       painter->SetOutlined("*",kFALSE);      
192       painter->SetOutlined("DE",kTRUE);
193       
194       painter->SetLine(1,4,3);      
195       ++i;
196     }
197     
198   }
199   
200   if ( painter ) 
201   {
202     pmf->ShiftClicked(painter,0x0);
203     
204     pmf->Update();
205   }
206       
207 }
208
209 //______________________________________________________________________________
210 AliMUONMchViewApplication::~AliMUONMchViewApplication()
211 {
212   /// dtor
213   delete fPainterMasterFrameList;
214 }
215
216 //_____________________________________________________________________________
217 AliMUONPainterMatrix*
218 AliMUONMchViewApplication::GenerateStartupMatrix()
219 {
220   /// Kind of bootstrap method to trigger the generation of all contours
221   
222   AliCodeTimerAuto("",0);
223   
224   AliMUONAttPainter att;
225   
226   att.SetViewPoint(kTRUE,kFALSE);
227   att.SetCathode(kFALSE,kFALSE);
228   att.SetPlane(kTRUE,kFALSE);
229
230   AliMUONPainterMatrix* matrix = new AliMUONPainterMatrix("Tracker",5,2);
231     
232   for ( Int_t i = 0; i < 10; ++i )
233   {
234     AliMUONVPainter* painter = new AliMUONChamberPainter(att,i);
235     
236     painter->SetResponder("Chamber");
237     
238     painter->SetOutlined("*",kFALSE);
239     
240     painter->SetOutlined("MANU",kTRUE);
241     
242     for ( Int_t j = 0; j < 3; ++j ) 
243     {
244       painter->SetLine(j,1,4-j);
245     }
246     
247     matrix->Adopt(painter);    
248   }
249   AliMUONPainterRegistry::Instance()->Register(matrix);
250   return matrix;
251 }
252
253 //______________________________________________________________________________
254 void
255 AliMUONMchViewApplication::CompareAlignments()
256 {
257   /// Launch compare data dialog
258   TGTransientFrame* t = new AliMUONAlignmentCompareDialog(gClient->GetRoot(),
259                                                           gClient->GetRoot(),
260                                                           400,400);
261   
262   t->MapSubwindows();
263   t->Resize();
264   t->MapWindow();
265   t->CenterOnParent();
266   
267   // set names
268   
269   t->SetWindowName("mchview compare alignments tool");
270   t->SetIconName("mchview compare alignments tool");
271   
272   t->MapRaised();  
273 }
274
275 //______________________________________________________________________________
276 void
277 AliMUONMchViewApplication::CompareData()
278 {
279   /// Launch compare data dialog
280   TGTransientFrame* t = new AliMUONTrackerDataCompareDialog(gClient->GetRoot(),
281                                                             gClient->GetRoot(),
282                                                             400,400);
283
284   t->MapSubwindows();
285   t->Resize();
286   t->MapWindow();
287   t->CenterOnParent();
288   
289   // set names
290   
291   t->SetWindowName("mchview compare data tool");
292   t->SetIconName("mchview compare data tool");
293   
294   t->MapRaised();  
295 }
296
297 //______________________________________________________________________________
298 void
299 AliMUONMchViewApplication::CreateMenuBar(UInt_t w)
300 {
301   /// Create the application menu bar
302   
303   TGPopupMenu* file = new TGPopupMenu(gClient->GetRoot());
304   
305   file->AddEntry("&Open...",fgkFILEOPEN);
306   file->AddEntry("&Save As...",fgkFILESAVEAS);
307   file->AddEntry("&Print As...",fgkFILEPRINTAS);
308   file->AddEntry("&Exit",fgkFILEEXIT);
309   
310   TGMenuBar* bar = new TGMenuBar(fMainFrame,w);
311   
312   TGPopupMenu* tools = new TGPopupMenu(gClient->GetRoot());
313   tools->AddEntry("&Compare data",fgkCOMPAREDATA);
314   tools->AddEntry("&Compare alignments",fgkCOMPAREALIGNMENTS);
315   
316   TGPopupMenu* about = new TGPopupMenu(gClient->GetRoot());  
317   about->AddEntry(FullVersion(),fgkABOUT);
318
319   file->Connect("Activated(Int_t)","AliMUONMchViewApplication",this,"HandleMenu(Int_t)");
320   about->Connect("Activated(Int_t)","AliMUONMchViewApplication",this,"HandleMenu(Int_t)");
321   tools->Connect("Activated(Int_t)","AliMUONMchViewApplication",this,"HandleMenu(Int_t)");
322   
323   bar->AddPopup("&File",file,new TGLayoutHints(kLHintsLeft|kLHintsTop));
324   bar->AddPopup("&Tools",tools,new TGLayoutHints(kLHintsLeft|kLHintsTop));
325   bar->AddPopup("&About",about,new TGLayoutHints(kLHintsRight|kLHintsTop));
326   
327   fMainFrame->AddFrame(bar,new TGLayoutHints(kLHintsLeft|kLHintsExpandX));
328   
329   AliMUONPainterRegistry::Instance()->SetMenuBar(bar);
330 }
331
332 //______________________________________________________________________________
333 void
334 AliMUONMchViewApplication::HandleMenu(Int_t i)
335 {
336   /// Handle the click of one menu item
337
338   switch (i)
339     {
340     case fgkFILEEXIT:
341       Terminate(1);
342       break;
343     case fgkFILEOPEN:
344       Open();
345       break;
346     case fgkFILESAVEAS:
347       Save();
348       break;
349     case fgkFILEPRINTAS:
350       PrintAs();
351       break;
352     case fgkABOUT:
353       ReleaseNotes();
354       break;
355     case fgkCOMPAREDATA:
356       CompareData();
357       break;
358     case fgkCOMPAREALIGNMENTS:
359       CompareAlignments();
360       break;
361       default:
362       break;
363     }
364 }
365
366 //______________________________________________________________________________
367 void
368 AliMUONMchViewApplication::Open()
369 {
370   /// Open file dialog
371   
372   TGFileInfo fileInfo;
373   
374   fileInfo.fFileTypes = fgkFileTypes;
375   
376   delete[] fileInfo.fIniDir;
377   
378   AliMUONPainterEnv* env = AliMUONPainterHelper::Instance()->Env();
379   
380   fileInfo.fIniDir = StrDup(env->String("LastOpenDir","."));
381   
382   new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),
383                    kFDOpen,&fileInfo);
384
385   env->Set("LastOpenDir",fileInfo.fIniDir);
386   env->Save();  
387     
388   Open(gSystem->ExpandPathName(Form("%s",fileInfo.fFilename)));
389 }  
390
391 //______________________________________________________________________________
392 void
393 AliMUONMchViewApplication::Open(const char* filename)
394 {
395   /// Open a given file containing saved VTrackerDataMaker objects
396   
397   TString sfilename(gSystem->ExpandPathName(filename));
398   
399   if ( sfilename.Contains(TRegexp("^alien")) )
400   {
401     // insure we've initialized the grid...
402     if (!gGrid)
403     {
404       TGrid::Connect("alien://");
405     }
406   }
407   
408   TFile* f = TFile::Open(filename);
409   
410         ReadDir(*f);
411         
412         delete f;
413 }
414
415 //______________________________________________________________________________
416 void
417 AliMUONMchViewApplication::ReadDir(TDirectory& dir)
418 {
419   /// Read the given directory and import VTrackerData objects found
420   
421   TList* keys = dir.GetListOfKeys();
422   TIter next(keys);
423   
424   TKey* k;
425   
426   while ( ( k = static_cast<TKey*>(next()) ) )
427   {
428     TObject* object = k->ReadObj();
429
430                 if ( object->InheritsFrom("TDirectory") )
431                 {
432                         TDirectory* d = static_cast<TDirectory*>(object);
433                         ReadDir(*d);
434                         continue;
435                 }
436                 
437     if ( object->InheritsFrom("AliMUONVTrackerDataMaker") )
438     {
439       AliMUONVTrackerDataMaker* maker = dynamic_cast<AliMUONVTrackerDataMaker*>(object);
440       if ( maker ) 
441       {
442         AliMUONPainterDataRegistry::Instance()->Register(maker);
443       }
444     }
445     
446     if ( object->InheritsFrom("AliMUONVTrackerData") )
447     {
448       // this is for backward compatibility. Early versions of mchview 
449       // wrote VTrackerData objects, and not VTrackerDataMaker ones.
450       
451       AliMUONVTrackerData* data = dynamic_cast<AliMUONVTrackerData*>(object);
452       if ( data ) 
453       {
454         AliMUONVTrackerDataMaker* maker = new AliMUONTrackerDataWrapper(data);
455         AliMUONPainterDataRegistry::Instance()->Register(maker);
456       }
457     }
458   }
459   
460
461
462 //______________________________________________________________________________
463 void
464 AliMUONMchViewApplication::PrintAs()
465 {
466   /// Print as...
467   
468   TGFileInfo fileInfo;
469   
470   new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),
471                    kFDSave,&fileInfo);
472   
473   TIter next(fPainterMasterFrameList);
474   AliMUONPainterMasterFrame* pmf;
475   Bool_t first(kTRUE);
476   
477   while ( ( pmf = static_cast<AliMUONPainterMasterFrame*>(next()) ) )
478   {
479     pmf->SaveAs(gSystem->ExpandPathName(Form("%s",fileInfo.fFilename)),
480                 first ? "RECREATE" : "UPDATE");
481     first = kFALSE;
482   }
483 }
484
485 //______________________________________________________________________________
486 void
487 AliMUONMchViewApplication::ReleaseNotes()
488 {
489   /// Display release notes
490   
491   UInt_t width = 600;
492   UInt_t height = 400;
493   
494   TGTransientFrame* t = new TGTransientFrame(gClient->GetRoot(),gClient->GetRoot(),width,height);
495   
496   TGTextView* rn = new TGTextView(t);
497
498   rn->AddLine("1.11");
499   rn->AddLine("");
500   rn->AddLine("Adding [Compare alignments] in the Tools menu + make default OCDB be 2012's version");
501   rn->AddLine("");
502   
503   rn->AddLine("1.10");
504   rn->AddLine("");
505   rn->AddLine("Make the raw OCDB more obvious in the data source tab");
506   rn->AddLine("");
507   
508   rn->AddLine("1.08");
509   rn->AddLine("");
510   rn->AddLine("Changed the default OCDB to 2011 version");
511   rn->AddLine("");
512   
513   rn->AddLine("1.07");
514   rn->AddLine("");
515   rn->AddLine("Added the RejectList as a possible OCDB data source");
516   rn->AddLine("");
517   
518   rn->AddLine("1.06");
519   rn->AddLine("");
520   rn->AddLine("Changed a bit the HV display. Now a trip is indicated with a value of -1");
521   rn->AddLine("");
522   
523   rn->AddLine("1.05");
524   rn->AddLine("");
525   rn->AddLine("Added the possibility to select an event range when reading raw data");
526   rn->AddLine("Usefull e.g. to look at a single suspect event...");
527   rn->AddLine("");
528   
529   rn->AddLine("1.04");
530   rn->AddLine("");
531   rn->AddLine("Changed the default OCDB to 2010 version");
532   rn->AddLine("");
533   
534   rn->AddLine("1.03");
535   rn->AddLine("");
536   rn->AddLine("Add Print buttons");
537   rn->AddLine("Add the automatic creation of often used canvases when using pedestal source");
538   // Internal reorganization to allow several independent tabs to be created to 
539   // show different master frames (not used yet). Important for the moment
540   // is the ability to create a PainterMatrix and pass it to the PainterMasterFrame
541   rn->AddLine("");
542   
543   rn->AddLine("1.02");
544   rn->AddLine("");
545   rn->AddLine("Internal change (merging of AliMUONTrackerACFDataMaker and AliMUONTrackerOCDBDataMaker into AliMUONTrackerConditionDataMaker)");
546   rn->AddLine("Added --ocdb option");
547   rn->AddLine("Corrected the display of the configuration");
548   rn->AddLine("Corrected the interpretation of the switches for the HV display");
549   rn->AddLine("");
550   
551   rn->AddLine("1.01");
552   rn->AddLine("");
553   rn->AddLine("Added the configuration as a possible OCDB data source");
554   rn->AddLine("");
555   
556   rn->AddLine("1.00");
557   rn->AddLine("");
558   rn->AddLine("Added the Status and StatusMap as a possible OCDB data source");
559   rn->AddLine("");
560   rn->AddLine("Added one (computed) dimension to the Gains data source = 1/a1/0.2 (mV/fC)");
561   rn->AddLine("");
562     
563   rn->AddLine("0.99a");
564   rn->AddLine("");
565   rn->AddLine("Added the --de and --chamber options");
566   rn->AddLine("");
567   
568   rn->AddLine("0.99");
569   rn->AddLine("");
570   rn->AddLine("The chamberid in the label (top right of panel) is now starting at 1 as in common usage");  
571   rn->AddLine("");
572   
573   rn->AddLine("0.98");
574   rn->AddLine("");
575   rn->AddLine("Added --asciimapping option");
576   rn->AddLine("");
577   
578   rn->AddLine("0.97");
579   rn->AddLine("");
580   rn->AddLine("Adding calibration option with Emelec (aka injection) gain");
581   rn->AddLine("");
582   
583   rn->AddLine("0.96a");
584   rn->AddLine("");
585   rn->AddLine("Internal reorganization of the contour computations, that lead to improved performance. ");
586   rn->AddLine("Improved enough to be able to remove completely the usage of the padstore.root file with precomputed contours.");
587   rn->AddLine("");
588   
589   rn->AddLine("0.96");
590   rn->AddLine("");
591   rn->AddLine("New features");
592   rn->AddLine("");
593   rn->AddLine("- Can now read raw data from memory (using the mem://@gdc: syntax)");
594   rn->AddLine("- Raw data decoder now automatically skips buspatches with parity errors");
595   rn->AddLine("");
596   
597   rn->AddLine("0.95");
598   rn->AddLine("");
599   rn->AddLine("New features");
600   rn->AddLine("");
601   rn->AddLine("- Can now read and display HV values from OCDB");
602   rn->AddLine("- New program option --geometry to force geometry of the window");
603   rn->AddLine("- Added possibility, in painters' context menu, to include or exclude part of the detector");
604   rn->AddLine("  (which will be used later on to communicate with LC2 which parts should be read out or not)");
605   rn->AddLine("");
606   rn->AddLine("Improvement");
607   rn->AddLine("");
608   rn->AddLine("- When displaying Gains, the quality information is now decoded");
609   rn->AddLine("");
610   
611   rn->AddLine("0.94");
612   rn->AddLine("");
613   rn->AddLine("New features");
614   rn->AddLine("");
615   rn->AddLine("Can now read ASCII calibration files produced by the DA");
616   rn->AddLine("");
617   
618   rn->AddLine("0.93");
619   rn->AddLine("");
620   rn->AddLine("New features");
621   rn->AddLine("");
622   rn->AddLine("- Adding a Lock button under the color slider to lock the range shown");
623   rn->AddLine("  when switching between views");
624   rn->AddLine("- Default display now shows bending plane (instead of cathode 0 before)");
625   rn->AddLine("- If pad is responder and there's some histo for that pad, ");
626   rn->AddLine("  clicking on it will display an histo");
627   rn->AddLine("- Right-click on a painter will now display several histogram options");
628   rn->AddLine("  (e.g. raw charge as before, but also simple distributions of mean");
629   rn->AddLine("  and sigma");
630   rn->AddLine("- In the Data Sources Tab, each data source can now be removed and saved");
631   rn->AddLine("- There's a new Tool menu which allow to produce a TrackerData from two others");
632   rn->AddLine("  in order to compare data.");
633   rn->AddLine("  - The --use option can now reference alien files");
634   rn->AddLine("");    
635   rn->AddLine("Bug fixes");
636   rn->AddLine("");    
637   rn->AddLine("- Can now read Capacitances from OCDB");
638     
639   rn->Resize(width,height);
640   
641   t->AddFrame(rn, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
642   
643   t->MapSubwindows();
644   t->Resize();
645   t->MapWindow();
646   t->CenterOnParent();
647     
648   // set names
649   
650   t->SetWindowName("mchview release notes");
651   t->SetIconName("mchview release notes");
652   
653 //  t->SetMWMHints(kMWMDecorAll | kMWMDecorResizeH  | kMWMDecorMaximize |
654 //              kMWMDecorMinimize | kMWMDecorMenu,
655 //              kMWMFuncAll  | kMWMFuncResize    | kMWMFuncMaximize |
656 //              kMWMFuncMinimize,
657 //              kMWMInputModeless);
658   
659   t->MapRaised();
660 //  gClient->WaitFor(t);
661 }
662
663 //______________________________________________________________________________
664 void
665 AliMUONMchViewApplication::Save()
666 {
667   /// Open "Save VTrackerData objects to file" dialog
668   
669   TGFileInfo fileInfo;
670   
671   new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),
672                    kFDSave,&fileInfo);
673   
674   Save(gSystem->ExpandPathName(Form("%s",fileInfo.fFilename)));
675 }  
676
677 //______________________________________________________________________________
678 void
679 AliMUONMchViewApplication::Save(const char* filename)
680 {
681   /// Save VTrackerDataMaker objects into file of given name
682   
683   AliMUONPainterDataRegistry* reg = AliMUONPainterDataRegistry::Instance();
684
685   TFile f(filename,"RECREATE");
686   
687   for ( Int_t i = 0; i < reg->NumberOfDataMakers(); ++i )
688   {
689     AliMUONVTrackerDataMaker* maker = reg->DataMaker(i);
690     maker->Write();
691   }
692   
693   f.Close();
694 }