TFitEditor.cxx

Go to the documentation of this file.
00001 // @(#)root/fitpanel:$Id: TFitEditor.cxx 35626 2010-09-23 08:32:43Z bellenot $
00002 // Author: Ilka Antcheva, Lorenzo Moneta 10/08/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 
00013 //////////////////////////////////////////////////////////////////////////
00014 //                                                                      //
00015 // TFitEditor                                                           //
00016 //                                                                      //
00017 // Allows to perform, explore and compare various fits.                 //
00018 //                                                                      //
00019 // To display the new Fit panel interface right click on a histogram    //
00020 // or a graph to pop up the context menu and then select the menu       //
00021 // entry 'Fit Panel'.                                                   //
00022 //                                                                      //
00023 // "General" Tab                                                        //
00024 //                                                                      //
00025 // The first set of GUI elements is related to the function choice      //
00026 // and settings. The status bar on the bottom provides information      //
00027 // about the current minimization settings using the following          //
00028 // abbreviations:                                                       //
00029 // LIB - shows the current choice between Minuit/Minuit2/Fumili         //
00030 // MIGRAD or FUMILI points to the current minimization method in use.   //
00031 // Itr: - shows the maximum number of iterations nnnn set for the fit.  //
00032 // Prn: - can be DEF/VER/QT and shows the current print option in use.  //
00033 //                                                                      //
00034 // "Predefined" combo box - contains a list of predefined functions     //
00035 // in ROOT. The default one is Gaussian.                                //
00036 //                                                                      //
00037 // "Operation" radio button group defines selected operational mode     //
00038 // between functions: NOP - no operation (default); ADD - addition      //
00039 // CONV - convolution (will be implemented in the future).              //
00040 //                                                                      //
00041 // Users can enter the function expression in a text entry field.       //
00042 // The entered string is checked after Enter key was pressed. An        //
00043 // error message shows up if the string is not accepted. The current    //
00044 // prototype is limited and users have no freedom to enter file/user    //
00045 // function names in this field.                                        //
00046 //                                                                      //
00047 // "Set Parameters" button opens a dialog for parameters settings.      //
00048 //                                                                      //
00049 // "Fit Settings" provides user interface elements related to the       //
00050 // fitter. Currently there are two method choices: Chi-square and       //
00051 // Binned Likelihood.                                                   //
00052 //                                                                      //
00053 // "Linear Fit" check button sets the use of Linear fitter is it is     //
00054 // selected. Otherwise the option 'F' is applied if polN is selected.   //
00055 // "Robust" number entry sets the robust value when fitting graphs.     //
00056 // "No Chi-square" check button sets ON/OFF option 'C' - do not         //
00057 // calculate Chi-square (for Linear fitter).                            //
00058 //                                                                      //
00059 // Fit options:                                                         //
00060 // "Integral" check button switch ON/OFF option 'I' - use integral      //
00061 // of function instead of value in bin center.                          //
00062 // "Best Errors" sets ON/OFF option 'E' - better errors estimation      //
00063 // using Minos technique.                                               //
00064 // "All weights = 1" sets ON/OFF option 'W' - all weights set to 1,     //
00065 // excluding empty bins and ignoring error bars.                        //
00066 // "Empty bins, weights=1" sets ON/OFF option 'WW' -  all weights       //
00067 // equal to 1, including  empty bins, error bars ignored.               //
00068 // "Use range" sets ON/OFF option 'R' - fit only data within the        //
00069 // specified function range with the slider.                            //
00070 // "Improve fit results" sets ON/OFF option 'M' - after minimum is      //
00071 // found, search for a new one.                                         //
00072 // "Add to list" sets On/Off option '+'- add function to the list       //
00073 // without deleting the previous.                                       //
00074 //                                                                      //
00075 // Draw options:                                                        //
00076 // "SAME" sets On/Off function drawing on the same pad.                 //
00077 // "No drawing" sets On/Off option '0'- do not draw function graphics.  //
00078 // "Do not store/draw" sets On/Off option 'N'- do not store the         //
00079 // function, do not draw it.                                            //
00080 //                                                                      //
00081 // Sliders settings are used if option 'R' - use range is active.       //
00082 // Users can change min/max values by pressing the left mouse button    //
00083 // near to the left/right slider edges. It is possible o change both    //
00084 // values simultaneously by pressing the left mouse button near to its  //
00085 // center and moving it to a new desire position.                       //
00086 //                                                                      //
00087 // "Minimization" Tab                                                   //
00088 //                                                                      //
00089 // "Library" group allows you to use Minuit, Minuit2 or Fumili          //
00090 // minimization packages for your fit.                                  //
00091 //  "Minuit" - the popular Minuit minimization package.                 //
00092 //  "Minuit2" - a new object-oriented implementation of Minuit in C++.  //
00093 //  "Fumili" - the popular Fumili minimization package.                 //
00094 //                                                                      //
00095 // "Method" group has currently restricted functionality.               //
00096 //  "MIGRAD" method is available for Minuit and Minuit2                 //
00097 //  "FUMILI" method is available for Fumili and Minuit2                 //
00098 //  "SIMPLEX" method is disabled (will come with the new fitter design) //
00099 //                                                                      //
00100 // "Minimization Settings' group allows users to set values for:        //
00101 //  "Error definition" - between 0.0 and 100.0  (default is 1.0).       //
00102 //  "Maximum tolerance" - the fit relative precision in use.            //
00103 //  "Maximum number of iterations" - default is 5000.                   //
00104 //                                                                      //
00105 // Print options:                                                       //
00106 //  "Default" - between Verbose and Quiet.                              //
00107 //  "Verbose" - prints results after each iteration.                    //
00108 //  "Quiet" - no fit information is printed.                            //
00109 //                                                                      //
00110 // Fit button - performs a fit.                                         //
00111 // Reset - resets all GUI elements and related fit settings to the      //
00112 // default ones.                                                        //
00113 // Close - closes this window.                                          //
00114 //                                                                      //
00115 // Begin_Html                                                           //
00116 /*
00117 <img src="gif/TFitEditor.gif">
00118 */
00119 //End_Html
00120 //////////////////////////////////////////////////////////////////////////
00121 
00122 #include "TFitEditor.h"
00123 #include "TROOT.h"
00124 #include "TClass.h"
00125 #include "TCanvas.h"
00126 #include "TGTab.h"
00127 #include "TGLabel.h"
00128 #include "TG3DLine.h"
00129 #include "TGComboBox.h"
00130 #include "TGTextEntry.h"
00131 #include "TGFont.h"
00132 #include "TGGC.h"
00133 #include "TGButtonGroup.h"
00134 #include "TGNumberEntry.h"
00135 #include "TGDoubleSlider.h"
00136 #include "TGStatusBar.h"
00137 #include "TFitParametersDialog.h"
00138 #include "TGMsgBox.h"
00139 #include "TAxis.h"
00140 #include "TGraph.h"
00141 #include "TGraph2D.h"
00142 #include "TH1.h"
00143 #include "TH2.h"
00144 #include "HFitInterface.h"
00145 #include "TF1.h"
00146 #include "TF2.h"
00147 #include "TF3.h"
00148 #include "TTimer.h"
00149 #include "THStack.h"
00150 #include "TMath.h"
00151 #include "Fit/UnBinData.h"
00152 #include "Fit/BinData.h"
00153 #include "Fit/BinData.h"
00154 #include "TMultiGraph.h"
00155 #include "TTree.h"
00156 #include "TTreePlayer.h"
00157 #include "TTreeInput.h"
00158 #include "TAdvancedGraphicsDialog.h"
00159 
00160 #include "RConfigure.h"
00161 #include "TPluginManager.h"
00162 
00163 #include <sstream>
00164 #include <vector>
00165 #include <queue>
00166 using std::vector;
00167 using std::queue;
00168 using std::pair;
00169 using std::ostringstream;
00170 using std::make_pair;
00171 
00172 #include "CommonDefs.h"
00173 
00174 // #include <iostream>
00175 // using std::cout;
00176 // using std::endl;
00177 
00178 void SearchCanvases(TSeqCollection* canvases, vector<TObject*>& objects);
00179 
00180 typedef std::multimap<TObject*, TF1*> FitFuncMap_t;
00181 
00182 //______________________________________________________________________________
00183 TF1* TFitEditor::FindFunction()
00184 {
00185    // This method looks among the functions stored by the fitpanel, the
00186    // one that is currently selected in the fFuncList
00187 
00188    // Get the list of functions from the system
00189    std::vector<TF1*>& funcList(fSystemFuncs);
00190 
00191    // Get the title/name of the function from fFuncList
00192    TGTextLBEntry *te = (TGTextLBEntry *)fFuncList->GetSelectedEntry();
00193    if ( !te ) return 0;
00194    TString name(te->GetTitle());
00195 
00196    // Look for a system function if it's USER DEFINED function
00197    if ( fTypeFit->GetSelected() == kFP_UFUNC ) {
00198       for ( fSystemFuncIter it = funcList.begin(); 
00199             it != funcList.end(); ++it ) {
00200          TF1* f = (*it);
00201          if ( strcmp( f->GetName(), name ) == 0 )
00202             // If found, return it.
00203             return f;
00204       }
00205    // If we are looking for previously fitted functions, look in the
00206    // fPrevFit data structure.
00207    } else if ( fTypeFit->GetSelected() == kFP_PREVFIT ) {
00208       pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(fFitObject);
00209       for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
00210          TF1* f = it->second;
00211          if ( strcmp( f->GetName(), name ) == 0 )
00212             // If found, return it
00213             return f;
00214       }
00215    }
00216 
00217    // Return a pointer to null if the function does not exist. This
00218    // will eventually create a segmentation fault, but the line should
00219    // never be executed.
00220    return 0;
00221 }
00222 
00223 //______________________________________________________________________________
00224 TF1* copyTF1(TF1* f)
00225 {
00226    //Copies f into a new TF1 to be stored in the fitpanel with it's
00227    //own ownership. This is taken from Fit::StoreAndDrawFitFunction in
00228    //HFitImpl.cxx
00229 
00230    double xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0; 
00231 
00232    if ( dynamic_cast<TF3*>(f) != 0 ) {
00233       TF3* fnew = (TF3*)f->IsA()->New();
00234       f->Copy(*fnew);
00235       f->GetRange(xmin,ymin,zmin,xmax,ymax,zmax);
00236       fnew->SetRange(xmin,ymin,zmin,xmax,ymax,zmax);
00237       fnew->SetParent( 0 );
00238       fnew->SetBit(TFormula::kNotGlobal);
00239       return fnew;
00240    } else if ( dynamic_cast<TF2*>(f) != 0 ) {
00241       TF2* fnew = (TF2*)f->IsA()->New();
00242       f->Copy(*fnew);
00243       f->GetRange(xmin,ymin,xmax,ymax);
00244       fnew->SetRange(xmin,ymin,xmax,ymax);
00245       fnew->Save(xmin,xmax,ymin,ymax,0,0);
00246       fnew->SetParent( 0 );
00247       fnew->SetBit(TFormula::kNotGlobal);
00248       return fnew;
00249    } else {
00250       TF1* fnew = (TF1*)f->IsA()->New();
00251       f->Copy(*fnew);
00252       f->GetRange(xmin,xmax);
00253       fnew->SetRange(xmin,xmax);
00254       // This next line is added, as fnew-Save fails with gausND! As
00255       // the number of dimensions is unknown...
00256       if ( '\0' != fnew->GetExpFormula()[0] )
00257          fnew->Save(xmin,xmax,0,0,0,0);
00258       fnew->SetParent( 0 );
00259       fnew->SetBit(TFormula::kNotGlobal);
00260       return fnew;
00261    }
00262 }
00263 
00264 //______________________________________________________________________________
00265 void GetParameters(TFitEditor::FuncParams_t & pars, TF1* func)
00266 {
00267    // Stores the parameters of the given function into pars
00268 
00269    int npar = func->GetNpar(); 
00270    if (npar != (int) pars.size() ) pars.resize(npar);
00271    for ( Int_t i = 0; i < npar; ++i )
00272    {
00273       Double_t par_min, par_max;
00274       pars[i][PAR_VAL] = func->GetParameter(i);
00275       func->GetParLimits(i, par_min, par_max);
00276       pars[i][PAR_MIN] = par_min;
00277       pars[i][PAR_MAX] = par_max;
00278    }
00279 }
00280 
00281 //______________________________________________________________________________
00282 void SetParameters(TFitEditor::FuncParams_t & pars, TF1* func)
00283 {
00284    // Restore the parameters from pars into the function
00285 
00286    int npar = func->GetNpar(); 
00287    if (npar > (int) pars.size() ) pars.resize(npar);
00288    for ( Int_t i = 0; i < npar; ++i )
00289    {
00290       func->SetParameter(i, pars[i][PAR_VAL]);
00291       func->SetParLimits(i, pars[i][PAR_MIN], pars[i][PAR_MAX]);
00292    }
00293 }
00294 
00295 //______________________________________________________________________________
00296 template<class FitObject>
00297 void InitParameters(TF1* func, FitObject * fitobj)
00298 {
00299    // Parameter initialization for the function
00300 
00301    const int special = func->GetNumber(); 
00302    if (100 == special || 400 == special) { 
00303       ROOT::Fit::BinData data; 
00304       ROOT::Fit::FillData(data,fitobj,func); 
00305       ROOT::Fit::InitGaus(data, func);
00306       // case gaussian or Landau
00307    } else if ( 110 == special || 410 == special ) {
00308       ROOT::Fit::BinData data;
00309       ROOT::Fit::FillData(data,fitobj,func);
00310       ROOT::Fit::Init2DGaus(data,func);
00311    }
00312 }
00313 
00314 //______________________________________________________________________________
00315 void GetTreeVarsAndCuts(TGComboBox* dataSet, TString& variablesStr, TString& cutsStr)
00316 {
00317    // Splits the entry in fDataSet to get the selected variables and cuts
00318    // from the text.
00319 
00320    // Get the entry
00321    TGTextLBEntry* textEntry = 
00322       static_cast<TGTextLBEntry*>( dataSet->GetListBox()->GetEntry( dataSet->GetSelected() ) );
00323    // Get the name of the tree
00324    TString nameStr ( textEntry->GetText()->GetString() );
00325    // Get the variables selected
00326    variablesStr = nameStr(nameStr.First('(') + 2, nameStr.First(',') - nameStr.First('(') - 3);
00327    // Get the cuts selected
00328    cutsStr = nameStr( nameStr.First(',') + 3, nameStr.First(')') - nameStr.First(',') - 4 );
00329 
00330    return;
00331 }
00332 
00333 
00334 ClassImp(TFitEditor)
00335 
00336 TFitEditor *TFitEditor::fgFitDialog = 0;
00337 
00338 //______________________________________________________________________________
00339 TFitEditor * TFitEditor::GetInstance(TVirtualPad* pad, TObject *obj)
00340 {
00341    // Static method - opens the fit panel.
00342 
00343    // Get the default pad if not provided.
00344    if (!pad)
00345    {
00346       if (!gPad)
00347          gROOT->MakeDefCanvas();
00348       pad = gPad;
00349    }
00350 
00351    if (!fgFitDialog) {
00352       fgFitDialog = new TFitEditor(pad, obj);
00353    } else {
00354       fgFitDialog->Show(pad, obj);
00355    }
00356    return fgFitDialog;
00357 }
00358 
00359 //______________________________________________________________________________
00360 TFitEditor::TFitEditor(TVirtualPad* pad, TObject *obj) :
00361    TGMainFrame(gClient->GetRoot(), 20, 20),
00362    fParentPad   (0),
00363    fFitObject   (0),
00364    fDim         (0),
00365    fXaxis       (0),
00366    fYaxis       (0),
00367    fZaxis       (0),
00368    fFuncPars    (0)
00369 
00370 {
00371    // Constructor of fit editor. 'obj' is the object to be fitted and
00372    // 'pad' where it is drawn.
00373 
00374    fType = kObjectHisto;
00375    SetCleanup(kDeepCleanup);
00376 
00377    TGCompositeFrame *tf = new TGCompositeFrame(this, 350, 26,
00378                                                 kHorizontalFrame);
00379    TGLabel *label = new TGLabel(tf,"Data Set: ");
00380    tf->AddFrame(label, new TGLayoutHints(kLHintsNormal, 15, 0, 5, 0));
00381 
00382    fDataSet = new TGComboBox(tf, kFP_DATAS);
00383    FillDataSetList();
00384    fDataSet->Resize(264, 20);
00385 
00386    tf->AddFrame(fDataSet, new TGLayoutHints(kLHintsNormal, 13, 0, 5, 0));
00387    fDataSet->Associate(this);
00388 
00389    this->AddFrame(tf, new TGLayoutHints(kLHintsNormal | kLHintsExpandX,0,0,5,5));
00390 
00391    CreateFunctionGroup();
00392    
00393    fTab = new TGTab(this, 10, 10);
00394    AddFrame(fTab, new TGLayoutHints(kLHintsExpandY | kLHintsExpandX));
00395    fTab->SetCleanup(kDeepCleanup);
00396    fTab->Associate(this);
00397    
00398    TGHorizontalFrame *cf1 = new TGHorizontalFrame(this, 350, 20, kFixedWidth);
00399    cf1->SetCleanup(kDeepCleanup);
00400    fUpdateButton = new TGTextButton(cf1, "&Update", kFP_UPDATE);
00401    fUpdateButton->Associate(this);
00402    cf1->AddFrame(fUpdateButton, new TGLayoutHints(kLHintsTop |
00403                                                   kLHintsExpandX, 0, 20, 2, 2));
00404 
00405 
00406    fFitButton = new TGTextButton(cf1, "&Fit", kFP_FIT);
00407    fFitButton->Associate(this);
00408    cf1->AddFrame(fFitButton, new TGLayoutHints(kLHintsTop |
00409                                                kLHintsExpandX, 15, -6, 2, 2));
00410 
00411    fResetButton = new TGTextButton(cf1, "&Reset", kFP_RESET);
00412    fResetButton->Associate(this);
00413    cf1->AddFrame(fResetButton, new TGLayoutHints(kLHintsTop |
00414                                                  kLHintsExpandX, 11, -2, 2, 2));
00415 
00416    fCloseButton = new TGTextButton(cf1, "&Close", kFP_CLOSE);
00417    fCloseButton->Associate(this);
00418    cf1->AddFrame(fCloseButton, new TGLayoutHints(kLHintsTop |
00419                                                  kLHintsExpandX, 7, 2, 2, 2));
00420    AddFrame(cf1, new TGLayoutHints(kLHintsNormal |
00421                                    kLHintsRight, 0, 5, 5, 5));
00422 
00423    // Create status bar
00424    int parts[] = { 20, 20, 20, 20, 20 };
00425    fStatusBar = new TGStatusBar(this, 10, 10);
00426    fStatusBar->SetParts(parts, 5);
00427    AddFrame(fStatusBar, new TGLayoutHints(kLHintsBottom | 
00428                                           kLHintsLeft   | 
00429                                           kLHintsExpandX));
00430 
00431    CreateGeneralTab();
00432    CreateMinimizationTab();
00433 
00434    gROOT->GetListOfCleanups()->Add(this);
00435 
00436    MapSubwindows();
00437    fGeneral->HideFrame(fSliderZParent);
00438 
00439    // do not allow resizing
00440    TGDimension size = GetDefaultSize();
00441    SetWindowName("Fit Panel");
00442    SetIconName("Fit Panel");
00443    SetClassHints("Fit Panel", "Fit Panel");
00444 
00445    SetMWMHints(kMWMDecorAll | kMWMDecorResizeH  | kMWMDecorMaximize |
00446                               kMWMDecorMinimize | kMWMDecorMenu,
00447                kMWMFuncAll  | kMWMFuncResize    | kMWMFuncMaximize |
00448                               kMWMFuncMinimize,
00449                kMWMInputModeless);
00450 
00451    ConnectSlots();
00452 
00453    GetFunctionsFromSystem();
00454 
00455    if (!obj) {
00456       TList* l = new TList();
00457       l->Add(pad);
00458       vector<TObject*> v;
00459       SearchCanvases(l, v);
00460       if ( v.size() ) 
00461          obj = v[0];
00462       delete l;
00463    }
00464 
00465    SetFitObject(pad, obj, kButton1Down);
00466 
00467    // In case we want to make it without a default canvas. This will
00468    // be implemented after the 5.21/06 Release. Remember to take out
00469    // any reference to the pad/canvas when the fitpanel is shown
00470    // and/or built.
00471 
00472    //SetCanvas(0 /*pad->GetCanvas()*/); 
00473 
00474    if ( pad ) {
00475       SetCanvas(pad->GetCanvas());
00476       if ( obj )
00477          pad->GetCanvas()->Selected(pad, obj, kButton1Down);
00478    }
00479 
00480    UInt_t dw = fClient->GetDisplayWidth();
00481    UInt_t cw = 0;
00482    UInt_t cx = 0;
00483    UInt_t cy = 0;
00484    if (pad && pad->GetCanvas() ) {
00485       cw = pad->GetCanvas()->GetWindowWidth();
00486       cx = (UInt_t)pad->GetCanvas()->GetWindowTopX();
00487       cy = (UInt_t)pad->GetCanvas()->GetWindowTopY();
00488    }
00489       
00490    Resize(size);
00491    MapWindow();
00492 
00493    if (cw + size.fWidth < dw) {
00494       Int_t gedx = 0, gedy = 0;
00495       gedx = cx+cw+4;
00496       gedy = cy-20;
00497       MoveResize(gedx, gedy,size.fWidth, size.fHeight);
00498       SetWMPosition(gedx, gedy);
00499    } 
00500 
00501    gVirtualX->RaiseWindow(GetId());
00502 
00503    ChangeOptions(GetOptions() | kFixedSize);
00504    SetWMSize(size.fWidth, size.fHeight);
00505    SetWMSizeHints(size.fWidth, size.fHeight, size.fWidth, size.fHeight, 0, 0);
00506 }
00507 
00508 //______________________________________________________________________________
00509 TFitEditor::~TFitEditor()
00510 {
00511    // Fit editor destructor.
00512 
00513    DisconnectSlots();
00514 
00515    // Disconnect all the slot that were no disconnected in DisconnecSlots
00516    fCloseButton->Disconnect("Clicked()");
00517    fDataSet->Disconnect("Selected(Int_t)");
00518    fUpdateButton->Disconnect("Clicked()");
00519    TQObject::Disconnect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)",
00520                         this, "SetFitObject(TVirtualPad *, TObject *, Int_t)");
00521    gROOT->GetListOfCleanups()->Remove(this);
00522 
00523    //Clean up the members that are not automatically cleaned.
00524    Cleanup();
00525    delete fLayoutNone;
00526    delete fLayoutAdd;
00527    delete fLayoutConv;
00528 
00529    // Set the singleton reference to null
00530    fgFitDialog = 0;
00531 }
00532 
00533 //______________________________________________________________________________
00534 void TFitEditor::CreateFunctionGroup()
00535 {
00536    // Creates the Frame that contains oll the information about the
00537    // function.
00538    TGGroupFrame *gf1 = new TGGroupFrame(this, "Fit Function", kFitWidth);
00539       
00540    TGCompositeFrame *tf0 = new TGCompositeFrame(gf1, 350, 26,
00541                                                 kHorizontalFrame);
00542    TGLabel *label1 = new TGLabel(tf0,"Type:");
00543    tf0->AddFrame(label1, new TGLayoutHints(kLHintsNormal, 0, 0, 5, 0));
00544 
00545    fTypeFit = new TGComboBox(tf0, kFP_TLIST);
00546    fTypeFit->AddEntry("User Func", kFP_UFUNC);
00547    fTypeFit->AddEntry("Predef-1D", kFP_PRED1D);
00548    fTypeFit->Resize(90, 20);
00549    fTypeFit->Select(kFP_PRED1D, kFALSE);
00550 
00551    TGListBox *lb = fTypeFit->GetListBox();
00552    lb->Resize(lb->GetWidth(), 200);
00553    tf0->AddFrame(fTypeFit, new TGLayoutHints(kLHintsNormal, 5, 0, 5, 0));
00554    fTypeFit->Associate(this);
00555 
00556    fFuncList = new TGComboBox(tf0, kFP_FLIST);
00557    FillFunctionList();
00558    fFuncList->Resize(194, 20);
00559    fFuncList->Select(kFP_GAUS, kFALSE);
00560 
00561    lb = fFuncList->GetListBox();
00562    lb->Resize(lb->GetWidth(), 500);
00563    tf0->AddFrame(fFuncList, new TGLayoutHints(kLHintsNormal, 5, 0, 5, 0));
00564    fFuncList->Associate(this);
00565 
00566    gf1->AddFrame(tf0, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
00567 
00568    TGCompositeFrame *tf1 = new TGCompositeFrame(gf1, 350, 26,
00569                                                 kHorizontalFrame);
00570    TGHButtonGroup *bgr = new TGHButtonGroup(tf1,"Operation");
00571    bgr->SetRadioButtonExclusive();
00572    fNone = new TGRadioButton(bgr, "Nop", kFP_NONE);
00573    fNone->SetToolTipText("No operation defined");
00574    fNone->SetState(kButtonDown, kFALSE);
00575    fAdd = new TGRadioButton(bgr, "Add", kFP_ADD);
00576    fAdd->SetToolTipText("Addition");
00577    fConv = new TGRadioButton(bgr, "Conv", kFP_CONV);
00578    fConv->SetToolTipText("Convolution (not implemented yet)");
00579    fConv->SetState(kButtonDisabled);
00580    fLayoutNone = new TGLayoutHints(kLHintsLeft,0,5,3,-10);
00581    fLayoutAdd  = new TGLayoutHints(kLHintsLeft,10,5,3,-10);
00582    fLayoutConv = new TGLayoutHints(kLHintsLeft,10,5,3,-10);
00583    bgr->SetLayoutHints(fLayoutNone,fNone);
00584    bgr->SetLayoutHints(fLayoutAdd,fAdd);
00585    bgr->SetLayoutHints(fLayoutConv,fConv);
00586    bgr->Show();
00587    bgr->ChangeOptions(kFitWidth | kHorizontalFrame);
00588    tf1->AddFrame(bgr, new TGLayoutHints(kLHintsNormal, 15, 0, 3, 0));
00589 
00590    gf1->AddFrame(tf1, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
00591 
00592    TGCompositeFrame *tf2 = new TGCompositeFrame(gf1, 350, 26,
00593                                                 kHorizontalFrame);
00594    fEnteredFunc = new TGTextEntry(tf2, new TGTextBuffer(0), kFP_FILE);
00595    //fEnteredFunc->SetMaxLength(4000);  // use default value (~4000)
00596    fEnteredFunc->SetAlignment(kTextLeft);
00597    TGTextLBEntry *te = (TGTextLBEntry *)fFuncList->GetSelectedEntry();
00598    assert(te);
00599    fEnteredFunc->SetText(te->GetTitle());
00600    fEnteredFunc->SetToolTipText("Enter file_name/function_name or a function expression");
00601    fEnteredFunc->Resize(250,fEnteredFunc->GetDefaultHeight());
00602    tf2->AddFrame(fEnteredFunc, new TGLayoutHints(kLHintsLeft    |
00603                                                  kLHintsCenterY |
00604                                                  kLHintsExpandX, 2, 2, 2, 2));
00605    gf1->AddFrame(tf2, new TGLayoutHints(kLHintsNormal |
00606                                         kLHintsExpandX, 0, 0, 2, 0));
00607 
00608    TGHorizontalFrame *s1 = new TGHorizontalFrame(gf1);
00609    TGLabel *label21 = new TGLabel(s1, "Selected: ");
00610    s1->AddFrame(label21, new TGLayoutHints(kLHintsNormal |
00611                                            kLHintsCenterY, 2, 2, 2, 0));
00612    TGHorizontal3DLine *hlines = new TGHorizontal3DLine(s1);
00613    s1->AddFrame(hlines, new TGLayoutHints(kLHintsCenterY | kLHintsExpandX));
00614    gf1->AddFrame(s1, new TGLayoutHints(kLHintsExpandX));
00615 
00616    TGCompositeFrame *tf4 = new TGCompositeFrame(gf1, 350, 26,
00617                                                 kHorizontalFrame);
00618    TGTextLBEntry *txt = (TGTextLBEntry *)fFuncList->GetSelectedEntry();
00619    TString s = txt->GetTitle();
00620    fSelLabel = new TGLabel(tf4, s.Sizeof()>30?s(0,30)+"...":s);
00621    tf4->AddFrame(fSelLabel, new TGLayoutHints(kLHintsNormal |
00622                                               kLHintsCenterY, 0, 6, 2, 0));
00623    Pixel_t color;
00624    gClient->GetColorByName("#336666", color);
00625    fSelLabel->SetTextColor(color, kFALSE);
00626    TGCompositeFrame *tf5 = new TGCompositeFrame(tf4, 120, 20,
00627                                                 kHorizontalFrame | kFixedWidth);
00628    fSetParam = new TGTextButton(tf5, "Set Parameters...", kFP_PARS);
00629    tf5->AddFrame(fSetParam, new TGLayoutHints(kLHintsRight   |
00630                                               kLHintsCenterY |
00631                                               kLHintsExpandX));
00632    fSetParam->SetToolTipText("Open a dialog for parameter(s) settings");
00633    tf4->AddFrame(tf5, new TGLayoutHints(kLHintsRight |
00634                                         kLHintsTop, 5, 0, 2, 2));
00635    gf1->AddFrame(tf4, new TGLayoutHints(kLHintsNormal |
00636                                              kLHintsExpandX, 5, 0, 0, 0));
00637 
00638    this->AddFrame(gf1, new TGLayoutHints(kLHintsExpandX, 5, 5, 0, 0));
00639 
00640 }
00641 
00642 //______________________________________________________________________________
00643 void TFitEditor::CreateGeneralTab()
00644 {
00645    // Create 'General' tab.
00646 
00647    fTabContainer = fTab->AddTab("General");
00648    fGeneral = new TGCompositeFrame(fTabContainer, 10, 10, kVerticalFrame);
00649    fTabContainer->AddFrame(fGeneral, new TGLayoutHints(kLHintsTop |
00650                                                        kLHintsExpandX,
00651                                                        5, 5, 2, 2));
00652 
00653    // 'options' group frame
00654    TGGroupFrame *gf = new TGGroupFrame(fGeneral, "Fit Settings", kFitWidth);
00655 
00656    // 'method' sub-group
00657    TGHorizontalFrame *h1 = new TGHorizontalFrame(gf);
00658    TGLabel *label4 = new TGLabel(h1, "Method");
00659    h1->AddFrame(label4, new TGLayoutHints(kLHintsNormal |
00660                                           kLHintsCenterY, 2, 2, 0, 0));
00661    TGHorizontal3DLine *hline1 = new TGHorizontal3DLine(h1);
00662    h1->AddFrame(hline1, new TGLayoutHints(kLHintsCenterY | kLHintsExpandX));
00663    gf->AddFrame(h1, new TGLayoutHints(kLHintsExpandX));
00664 
00665    TGHorizontalFrame *h2 = new TGHorizontalFrame(gf);
00666    TGVerticalFrame *v1 = new TGVerticalFrame(h2);
00667    fMethodList = BuildMethodList(v1, kFP_MLIST);
00668    fMethodList->Select(1, kFALSE);
00669    fMethodList->Resize(140, 20);
00670    TGListBox *lb = fMethodList->GetListBox();
00671    Int_t lbe = lb->GetNumberOfEntries();
00672    lb->Resize(lb->GetWidth(), lbe*16);
00673    v1->AddFrame(fMethodList, new TGLayoutHints(kLHintsLeft, 0, 0, 2, 5));
00674 
00675    fLinearFit = new TGCheckButton(v1, "Linear fit", kFP_MLINF);
00676    fLinearFit->Associate(this);
00677    fLinearFit->SetToolTipText("Perform Linear fitter if selected");
00678    v1->AddFrame(fLinearFit, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00679 
00680    TGHorizontalFrame *v1h = new TGHorizontalFrame(v1);
00681    TGLabel *label41 = new TGLabel(v1h, "Robust:");
00682    v1h->AddFrame(label41, new TGLayoutHints(kLHintsNormal |
00683                                             kLHintsCenterY, 25, 5, 5, 2));
00684    fRobustValue = new TGNumberEntry(v1h, 1., 5, kFP_RBUST,
00685                                     TGNumberFormat::kNESRealTwo,
00686                                     TGNumberFormat::kNEAPositive,
00687                                     TGNumberFormat::kNELLimitMinMax,0.,1.);
00688    v1h->AddFrame(fRobustValue, new TGLayoutHints(kLHintsLeft));
00689    v1->AddFrame(v1h, new TGLayoutHints(kLHintsNormal));
00690    fRobustValue->SetState(kFALSE);
00691    fRobustValue->GetNumberEntry()->SetToolTipText("Available only for graphs");
00692 
00693    h2->AddFrame(v1, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00694 
00695    TGVerticalFrame *v2 = new TGVerticalFrame(h2);
00696    TGCompositeFrame *v21 = new TGCompositeFrame(v2, 120, 20,
00697                                                 kHorizontalFrame | kFixedWidth);
00698    fUserButton = new TGTextButton(v21, "User-Defined...", kFP_MUSR);
00699    v21->AddFrame(fUserButton, new TGLayoutHints(kLHintsRight   |
00700                                                 kLHintsCenterY |
00701                                                 kLHintsExpandX));
00702    fUserButton->SetToolTipText("Open a dialog for entering a user-defined method");
00703    fUserButton->SetState(kButtonDisabled);
00704    v2->AddFrame(v21, new TGLayoutHints(kLHintsRight | kLHintsTop));
00705 
00706    fNoChi2 = new TGCheckButton(v2, "No Chi-square", kFP_NOCHI);
00707    fNoChi2->Associate(this);
00708    fNoChi2->SetToolTipText("'C'- do not calculate Chi-square (for Linear fitter)");
00709    v2->AddFrame(fNoChi2, new TGLayoutHints(kLHintsNormal, 0, 0, 34, 2));
00710 
00711    h2->AddFrame(v2, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 20, 0, 0, 0));
00712    gf->AddFrame(h2, new TGLayoutHints(kLHintsExpandX, 20, 0, 0, 0));
00713 
00714    // 'fit option' sub-group
00715    TGHorizontalFrame *h3 = new TGHorizontalFrame(gf);
00716    TGLabel *label5 = new TGLabel(h3, "Fit Options");
00717    h3->AddFrame(label5, new TGLayoutHints(kLHintsNormal |
00718                                           kLHintsCenterY, 2, 2, 0, 0));
00719    TGHorizontal3DLine *hline2 = new TGHorizontal3DLine(h3);
00720    h3->AddFrame(hline2, new TGLayoutHints(kLHintsCenterY | kLHintsExpandX));
00721    gf->AddFrame(h3, new TGLayoutHints(kLHintsExpandX));
00722 
00723    TGHorizontalFrame *h = new TGHorizontalFrame(gf);
00724    TGVerticalFrame *v3 = new TGVerticalFrame(h);
00725    fIntegral = new TGCheckButton(v3, "Integral", kFP_INTEG);
00726    fIntegral->Associate(this);
00727    fIntegral->SetToolTipText("'I'- use integral of function instead of value in bin center");
00728    v3->AddFrame(fIntegral, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00729 
00730    fBestErrors = new TGCheckButton(v3, "Best errors", kFP_IMERR);
00731    fBestErrors->Associate(this);
00732    fBestErrors->SetToolTipText("'E'- better errors estimation using Minos technique");
00733    v3->AddFrame(fBestErrors, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00734 
00735    fAllWeights1 = new TGCheckButton(v3, "All weights = 1", kFP_ALLW1);
00736    fAllWeights1->Associate(this);
00737    fAllWeights1->SetToolTipText("'W'- all weights=1 for non empty bins; error bars ignored");
00738    v3->AddFrame(fAllWeights1, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00739 
00740    fEmptyBinsWghts1 = new TGCheckButton(v3, "Empty bins, weights=1", kFP_EMPW1);
00741    fEmptyBinsWghts1->Associate(this);
00742    fEmptyBinsWghts1->SetToolTipText("'WW'- all weights=1 including empty bins; error bars ignored");
00743    v3->AddFrame(fEmptyBinsWghts1, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00744 
00745    h->AddFrame(v3, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00746 
00747    TGVerticalFrame *v4 = new TGVerticalFrame(h);
00748    fUseRange = new TGCheckButton(v4, "Use range", kFP_USERG);
00749    fUseRange->Associate(this);
00750    fUseRange->SetToolTipText("'R'- fit only data within the specified function range");
00751    v4->AddFrame(fUseRange, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00752 
00753    fImproveResults = new TGCheckButton(v4, "Improve fit results", kFP_IFITR);
00754    fImproveResults->Associate(this);
00755    fImproveResults->SetToolTipText("'M'- after minimum is found, search for a new one");
00756    v4->AddFrame(fImproveResults, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00757 
00758    fAdd2FuncList = new TGCheckButton(v4, "Add to list", kFP_ADDLS);
00759    fAdd2FuncList->Associate(this);
00760    fAdd2FuncList->SetToolTipText("'+'- add function to the list without deleting the previous");
00761    v4->AddFrame(fAdd2FuncList, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00762 
00763    fUseGradient = new TGCheckButton(v4, "Use Gradient", kFP_ADDLS);
00764    fUseGradient->Associate(this);
00765    fUseGradient->SetToolTipText("'G'- Use the gradient as an aid for the fitting");
00766    v4->AddFrame(fUseGradient, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00767 
00768    h->AddFrame(v4, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 20, 0, 0, 0));
00769    gf->AddFrame(h, new TGLayoutHints(kLHintsExpandX, 20, 0, 0, 0));
00770 
00771    // 'draw option' sub-group
00772    TGHorizontalFrame *h5 = new TGHorizontalFrame(gf);
00773    TGLabel *label6 = new TGLabel(h5, "Draw Options");
00774    h5->AddFrame(label6, new TGLayoutHints(kLHintsNormal |
00775                                           kLHintsCenterY, 2, 2, 2, 2));
00776    TGHorizontal3DLine *hline3 = new TGHorizontal3DLine(h5);
00777    h5->AddFrame(hline3, new TGLayoutHints(kLHintsCenterY | kLHintsExpandX));
00778    gf->AddFrame(h5, new TGLayoutHints(kLHintsExpandX));
00779 
00780    TGHorizontalFrame *h6 = new TGHorizontalFrame(gf);
00781    TGVerticalFrame *v5 = new TGVerticalFrame(h6);
00782 
00783    fDrawSame = new TGCheckButton(v5, "SAME", kFP_DSAME);
00784    fDrawSame->Associate(this);
00785    fDrawSame->SetToolTipText("Superimpose on previous picture in the same pad");
00786    v5->AddFrame(fDrawSame, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00787 
00788    fNoDrawing = new TGCheckButton(v5, "No drawing", kFP_DNONE);
00789    fNoDrawing->Associate(this);
00790    fNoDrawing->SetToolTipText("'0'- do not draw function graphics");
00791    v5->AddFrame(fNoDrawing, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00792 
00793    fNoStoreDrawing = new TGCheckButton(v5, "Do not store/draw", kFP_DNOST);
00794    fNoStoreDrawing->Associate(this);
00795    fNoStoreDrawing->SetToolTipText("'N'- do not store the function, do not draw it");
00796    v5->AddFrame(fNoStoreDrawing, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
00797 
00798    h6->AddFrame(v5, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00799 
00800    TGVerticalFrame *v6 = new TGVerticalFrame(h6);
00801    TGCompositeFrame *v61 = new TGCompositeFrame(v6, 120, 20,
00802                                                 kHorizontalFrame | kFixedWidth);
00803    fDrawAdvanced = new TGTextButton(v61, "&Advanced...", kFP_DADVB);
00804    v61->AddFrame(fDrawAdvanced, new TGLayoutHints(kLHintsRight   |
00805                                                   kLHintsCenterY |
00806                                                   kLHintsExpandX));
00807    fDrawAdvanced->SetToolTipText("Open a dialog for advanced draw options");
00808    fDrawAdvanced->SetState(kButtonDisabled);
00809 
00810    v6->AddFrame(v61, new TGLayoutHints(kLHintsRight | kLHintsTop,
00811                                        0, 0, (4+fDrawSame->GetHeight())*2, 0));
00812 
00813    h6->AddFrame(v6, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));
00814    gf->AddFrame(h6, new TGLayoutHints(kLHintsExpandX, 20, 0, 2, 0));
00815 
00816    fGeneral->AddFrame(gf, new TGLayoutHints(kLHintsExpandX |
00817                                             kLHintsExpandY, 5, 5, 0, 0));
00818    // sliderX
00819    fSliderXParent = new TGHorizontalFrame(fGeneral);
00820    TGLabel *label8 = new TGLabel(fSliderXParent, "X");
00821    fSliderXParent->AddFrame(label8, new TGLayoutHints(kLHintsLeft |
00822                                                       kLHintsCenterY, 0, 5, 0, 0));
00823 
00824    fSliderXMin = new TGNumberEntry(fSliderXParent, 0, 5, kFP_XMIN,
00825                                    TGNumberFormat::kNESRealTwo,
00826                                    TGNumberFormat::kNEAAnyNumber,
00827                                    TGNumberFormat::kNELLimitMinMax, -1,1);
00828    fSliderXParent->AddFrame(fSliderXMin, new TGLayoutHints(kLHintsLeft | kLHintsCenterY));
00829 
00830    fSliderX = new TGDoubleHSlider(fSliderXParent, 1, kDoubleScaleBoth);
00831    fSliderX->SetScale(5);
00832    fSliderXParent->AddFrame(fSliderX, new TGLayoutHints(kLHintsExpandX | kLHintsCenterY));
00833 
00834 
00835    fSliderXMax = new TGNumberEntry(fSliderXParent, 0, 5, kFP_XMIN,
00836                                    TGNumberFormat::kNESRealTwo,
00837                                    TGNumberFormat::kNEAAnyNumber,
00838                                    TGNumberFormat::kNELLimitMinMax, -1,1);
00839    fSliderXParent->AddFrame(fSliderXMax, new TGLayoutHints(kLHintsRight | kLHintsCenterY));
00840    fGeneral->AddFrame(fSliderXParent, new TGLayoutHints(kLHintsExpandX, 5, 5, 0, 0));
00841 
00842    // sliderY
00843    fSliderYParent = new TGHorizontalFrame(fGeneral);
00844    TGLabel *label9 = new TGLabel(fSliderYParent, "Y");
00845    fSliderYParent->AddFrame(label9, new TGLayoutHints(kLHintsLeft |
00846                                                       kLHintsCenterY, 0, 5, 0, 0));
00847 
00848    fSliderYMin = new TGNumberEntry(fSliderYParent, 0, 5, kFP_YMIN,
00849                                    TGNumberFormat::kNESRealTwo,
00850                                    TGNumberFormat::kNEAAnyNumber,
00851                                    TGNumberFormat::kNELLimitMinMax, -1,1);
00852    fSliderYParent->AddFrame(fSliderYMin, new TGLayoutHints(kLHintsLeft | kLHintsCenterY));
00853 
00854    fSliderY = new TGDoubleHSlider(fSliderYParent, 1, kDoubleScaleBoth);
00855    fSliderY->SetScale(5);
00856    fSliderYParent->AddFrame(fSliderY, new TGLayoutHints(kLHintsExpandX | kLHintsCenterY));
00857 
00858    fSliderYMax = new TGNumberEntry(fSliderYParent, 0, 5, kFP_YMIN,
00859                                    TGNumberFormat::kNESRealTwo,
00860                                    TGNumberFormat::kNEAAnyNumber,
00861                                    TGNumberFormat::kNELLimitMinMax, -1,1);
00862    fSliderYParent->AddFrame(fSliderYMax, new TGLayoutHints(kLHintsRight | kLHintsCenterY));
00863    fGeneral->AddFrame(fSliderYParent, new TGLayoutHints(kLHintsExpandX, 5, 5, 0, 0));
00864 
00865    // sliderZ
00866    fSliderZParent = new TGHorizontalFrame(fGeneral);
00867    TGLabel *label10 = new TGLabel(fSliderZParent, "Z:");
00868    fSliderZParent->AddFrame(label10, new TGLayoutHints(kLHintsLeft |
00869                                                        kLHintsCenterY, 0, 5, 0, 0));
00870    fSliderZ = new TGDoubleHSlider(fSliderZParent, 1, kDoubleScaleBoth);
00871    fSliderZ->SetScale(5);
00872    fSliderZParent->AddFrame(fSliderZ, new TGLayoutHints(kLHintsExpandX | 
00873                                                         kLHintsCenterY));
00874    fGeneral->AddFrame(fSliderZParent, new TGLayoutHints(kLHintsExpandX, 5, 5, 0, 0));
00875 }
00876 
00877 
00878 //______________________________________________________________________________
00879 void TFitEditor::CreateMinimizationTab()
00880 {
00881    // Create 'Minimization' tab.
00882    
00883    fTabContainer = fTab->AddTab("Minimization");
00884    fMinimization = new TGCompositeFrame(fTabContainer, 10, 10, kVerticalFrame);
00885    fTabContainer->AddFrame(fMinimization, new TGLayoutHints(kLHintsTop |
00886                                                             kLHintsExpandX,
00887                                                             5, 5, 2, 2));
00888    MakeTitle(fMinimization, "Library");
00889 
00890    TGHorizontalFrame *hl = new TGHorizontalFrame(fMinimization);
00891    fLibMinuit = new TGRadioButton(hl, "Minuit", kFP_LMIN);
00892    fLibMinuit->Associate(this);
00893    fLibMinuit->SetToolTipText("Use minimization from libMinuit (default)");
00894    hl->AddFrame(fLibMinuit, new TGLayoutHints(kLHintsNormal, 40, 0, 0, 1));
00895    fStatusBar->SetText("LIB Minuit",1);
00896 
00897    fLibMinuit2 = new TGRadioButton(hl, "Minuit2", kFP_LMIN2);
00898    fLibMinuit2->Associate(this);
00899    fLibMinuit2->SetToolTipText("New C++ version of Minuit");
00900    hl->AddFrame(fLibMinuit2, new TGLayoutHints(kLHintsNormal, 35, 0, 0, 1));
00901 
00902    fLibFumili = new TGRadioButton(hl, "Fumili", kFP_LFUM);
00903    fLibFumili->Associate(this);
00904    fLibFumili->SetToolTipText("Use minimization from libFumili");
00905    hl->AddFrame(fLibFumili, new TGLayoutHints(kLHintsNormal, 30, 0, 0, 1));
00906    fMinimization->AddFrame(hl, new TGLayoutHints(kLHintsExpandX, 20, 0, 5, 1));
00907 
00908    TGHorizontalFrame *hl2 = new TGHorizontalFrame(fMinimization);
00909 
00910    fLibGSL = new TGRadioButton(hl2, "GSL", kFP_LGSL);
00911    #ifdef R__HAS_MATHMORE
00912    fLibGSL->Associate(this);
00913    fLibGSL->SetToolTipText("Use minimization from libGSL");
00914    #else
00915    fLibGSL->SetState(kButtonDisabled);
00916    fLibGSL->SetToolTipText("Needs GSL to be compiled");
00917    #endif
00918    hl2->AddFrame(fLibGSL, new TGLayoutHints(kLHintsNormal, 40, 0, 0, 1));
00919 
00920    fLibGenetics = new TGRadioButton(hl2, "Genetics", kFP_LGAS);
00921    if (gPluginMgr->FindHandler("ROOT::Math::Minimizer","Genetic") ||
00922        gPluginMgr->FindHandler("ROOT::Math::Minimizer","GAlibMin") )
00923    {
00924       fLibGenetics->Associate(this);
00925       fLibGenetics->SetToolTipText("Different GAs implementations");
00926    } else {
00927       fLibGenetics->SetState(kButtonDisabled);
00928       fLibGenetics->SetToolTipText("Needs any of the genetic" 
00929                                    "minimizers to be compiled");
00930    }
00931    hl2->AddFrame(fLibGenetics, new TGLayoutHints(kLHintsNormal, 45, 0, 0, 1));
00932 
00933    fMinimization->AddFrame(hl2, new TGLayoutHints(kLHintsExpandX, 20, 0, 5, 1));
00934 
00935    MakeTitle(fMinimization, "Method");
00936 
00937    TGHorizontalFrame *hm0 = new TGHorizontalFrame(fMinimization);
00938    fMinMethodList = new TGComboBox(hm0, kFP_MINMETHOD);
00939    fMinMethodList->Resize(290, 20);
00940    fMinMethodList->Select(kFP_GAUS, kFALSE);
00941 
00942    TGListBox *lb = fMinMethodList->GetListBox();
00943    lb->Resize(lb->GetWidth(), 500);
00944    fMinMethodList->Associate(this);
00945 
00946    hm0->AddFrame(fMinMethodList, new TGLayoutHints(kLHintsNormal));
00947    fMinimization->AddFrame(hm0, new TGLayoutHints(kLHintsExpandX, 60, 0, 5, 1));
00948 
00949    // Set the status to the default minimization options!
00950    if ( ROOT::Math::MinimizerOptions::DefaultMinimizerType() == "Fumili" ) {
00951       fLibFumili->SetState(kButtonDown);
00952    } else if ( ROOT::Math::MinimizerOptions::DefaultMinimizerType() == "Minuit" ) {
00953       fLibMinuit->SetState(kButtonDown);
00954    } else {
00955       fLibMinuit2->SetState(kButtonDown);
00956    }
00957    FillMinMethodList();
00958 
00959    MakeTitle(fMinimization, "Settings");
00960    TGLabel *hslabel1 = new TGLabel(fMinimization,"Use ENTER key to validate a new value or click");
00961    fMinimization->AddFrame(hslabel1, new TGLayoutHints(kLHintsNormal, 61, 0, 5, 1));
00962    TGLabel *hslabel2 = new TGLabel(fMinimization,"on Reset button to set the defaults.");
00963    fMinimization->AddFrame(hslabel2, new TGLayoutHints(kLHintsNormal, 61, 0, 1, 10));
00964 
00965    TGHorizontalFrame *hs = new TGHorizontalFrame(fMinimization);
00966    
00967    TGVerticalFrame *hsv1 = new TGVerticalFrame(hs, 180, 10, kFixedWidth);
00968    TGLabel *errlabel = new TGLabel(hsv1,"Error definition (default = 1): ");
00969    hsv1->AddFrame(errlabel, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 
00970                                               1, 1, 5, 7));
00971    TGLabel *tollabel = new TGLabel(hsv1,"Max tolerance (precision): ");
00972    hsv1->AddFrame(tollabel, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 
00973                                               1, 1, 5, 7));
00974    TGLabel *itrlabel = new TGLabel(hsv1,"Max number of iterations: ");
00975    hsv1->AddFrame(itrlabel, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 
00976                                               1, 1, 5, 5));
00977    hs->AddFrame(hsv1, new TGLayoutHints(kLHintsNormal, 60, 0, 0, 0));
00978    
00979    TGVerticalFrame *hsv2 = new TGVerticalFrame(hs, 90,10, kFixedWidth);
00980    fErrorScale = new TGNumberEntryField(hsv2, kFP_MERR, ROOT::Math::MinimizerOptions::DefaultErrorDef(),
00981                                         TGNumberFormat::kNESRealTwo,
00982                                         TGNumberFormat::kNEAPositive,
00983                                         TGNumberFormat::kNELLimitMinMax,0.,100.);
00984    hsv2->AddFrame(fErrorScale, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 
00985                                                  1, 1, 0, 3));
00986    fTolerance = new TGNumberEntryField(hsv2, kFP_MTOL, ROOT::Math::MinimizerOptions::DefaultTolerance(), 
00987                                        TGNumberFormat::kNESReal,
00988                                        TGNumberFormat::kNEAPositive,
00989                                        TGNumberFormat::kNELLimitMinMax, 0., 1.);
00990    fTolerance->SetNumber(ROOT::Math::MinimizerOptions::DefaultTolerance());
00991    hsv2->AddFrame(fTolerance, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 
00992                                                 1, 1, 3, 3));
00993    fIterations = new TGNumberEntryField(hsv2, kFP_MITR, 5000, 
00994                                    TGNumberFormat::kNESInteger,
00995                                    TGNumberFormat::kNEAPositive,
00996                                    TGNumberFormat::kNELNoLimits);
00997    fIterations->SetNumber(ROOT::Math::MinimizerOptions::DefaultMaxIterations());
00998    hsv2->AddFrame(fIterations, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 
00999                                                  1, 1, 3, 3));
01000    hs->AddFrame(hsv2, new TGLayoutHints(kLHintsNormal, 0, 0, 0, 0));
01001    fMinimization->AddFrame(hs, new TGLayoutHints(kLHintsExpandX, 0, 0, 1, 1));
01002    fStatusBar->SetText(Form("Itr: %d",ROOT::Math::MinimizerOptions::DefaultMaxIterations()),3);
01003 
01004    MakeTitle(fMinimization, "Print Options");
01005 
01006    TGHorizontalFrame *h8 = new TGHorizontalFrame(fMinimization);
01007    fOptDefault = new TGRadioButton(h8, "Default", kFP_PDEF);
01008    fOptDefault->Associate(this);
01009    fOptDefault->SetToolTipText("Default is between Verbose and Quiet");
01010    h8->AddFrame(fOptDefault, new TGLayoutHints(kLHintsNormal, 40, 0, 0, 1));
01011    fOptDefault->SetState(kButtonDown);
01012    fStatusBar->SetText("Prn: DEF",4);
01013 
01014    fOptVerbose = new TGRadioButton(h8, "Verbose", kFP_PVER);
01015    fOptVerbose->Associate(this);
01016    fOptVerbose->SetToolTipText("'V'- print results after each iteration");
01017    h8->AddFrame(fOptVerbose, new TGLayoutHints(kLHintsNormal, 30, 0, 0, 1));
01018 
01019    fOptQuiet = new TGRadioButton(h8, "Quiet", kFP_PQET);
01020    fOptQuiet->Associate(this);
01021    fOptQuiet->SetToolTipText("'Q'- no print");
01022    h8->AddFrame(fOptQuiet, new TGLayoutHints(kLHintsNormal, 25, 0, 0, 1));
01023 
01024    fMinimization->AddFrame(h8, new TGLayoutHints(kLHintsExpandX, 20, 0, 5, 1));
01025 
01026 }
01027 
01028 //______________________________________________________________________________
01029 void TFitEditor::ConnectSlots()
01030 {
01031    // Connect GUI signals to fit panel slots.
01032 
01033    // list of data sets to fit
01034    fDataSet->Connect("Selected(Int_t)", "TFitEditor", this, "DoDataSet(Int_t)");
01035    // list of predefined functions
01036    fTypeFit->Connect("Selected(Int_t)", "TFitEditor", this, "FillFunctionList(Int_t)");
01037    // list of predefined functions
01038    fFuncList->Connect("Selected(Int_t)", "TFitEditor", this, "DoFunction(Int_t)");
01039    // entered formula or function name
01040    fEnteredFunc->Connect("ReturnPressed()", "TFitEditor", this, "DoEnteredFunction()");
01041    // set parameters dialog
01042    fSetParam->Connect("Clicked()", "TFitEditor", this, "DoSetParameters()");
01043    // allowed function operations
01044    fAdd->Connect("Toggled(Bool_t)","TFitEditor", this, "DoAddition(Bool_t)");
01045 
01046    // fit options
01047    fAllWeights1->Connect("Toggled(Bool_t)","TFitEditor",this,"DoAllWeights1()");
01048    fUseRange->Connect("Toggled(Bool_t)","TFitEditor",this,"DoUseFuncRange()");
01049    fEmptyBinsWghts1->Connect("Toggled(Bool_t)","TFitEditor",this,"DoEmptyBinsAllWeights1()");
01050 
01051    // linear fit
01052    fLinearFit->Connect("Toggled(Bool_t)","TFitEditor",this,"DoLinearFit()");
01053    fNoChi2->Connect("Toggled(Bool_t)","TFitEditor",this,"DoNoChi2()");
01054 
01055    // draw options
01056    fNoStoreDrawing->Connect("Toggled(Bool_t)","TFitEditor",this,"DoNoStoreDrawing()");
01057 
01058    // fit, reset, close buttons
01059    fUpdateButton->Connect("Clicked()", "TFitEditor", this, "DoUpdate()");
01060    fFitButton->Connect("Clicked()", "TFitEditor", this, "DoFit()");
01061    fResetButton->Connect("Clicked()", "TFitEditor", this, "DoReset()");
01062    fCloseButton->Connect("Clicked()", "TFitEditor", this, "DoClose()");
01063 
01064    // user method button
01065    fUserButton->Connect("Clicked()", "TFitEditor", this, "DoUserDialog()");
01066    // advanced draw options
01067    fDrawAdvanced->Connect("Clicked()", "TFitEditor", this, "DoAdvancedOptions()");
01068 
01069    if (fType != kObjectTree) {
01070       fSliderX->Connect("PositionChanged()","TFitEditor",this, "DoSliderXMoved()");
01071       fSliderXMax->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderXChanged()");
01072       fSliderXMin->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderXChanged()");
01073    }
01074    if (fDim > 1) {
01075       fSliderY->Connect("PositionChanged()","TFitEditor",this, "DoSliderYMoved()");
01076       fSliderYMax->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderYChanged()");
01077       fSliderYMin->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderYChanged()");
01078    }
01079    if (fDim > 2)
01080       fSliderZ->Connect("PositionChanged()","TFitEditor",this, "DoSliderZMoved()");
01081 
01082    if ( fParentPad )
01083       fParentPad->Connect("RangeAxisChanged()", "TFitEditor", this, "UpdateGUI()");
01084    
01085    // 'Minimization' tab
01086    // library
01087    fLibMinuit->Connect("Toggled(Bool_t)","TFitEditor",this,"DoLibrary(Bool_t)");
01088    fLibMinuit2->Connect("Toggled(Bool_t)","TFitEditor",this,"DoLibrary(Bool_t)");
01089    fLibFumili->Connect("Toggled(Bool_t)","TFitEditor",this,"DoLibrary(Bool_t)");
01090    fLibGSL->Connect("Toggled(Bool_t)","TFitEditor",this,"DoLibrary(Bool_t)");
01091    fLibGenetics->Connect("Toggled(Bool_t)","TFitEditor",this,"DoLibrary(Bool_t)");
01092 
01093    // minimization method
01094    fMinMethodList->Connect("Selected(Int_t)", "TFitEditor", this, "DoMinMethod(Int_t)");
01095 
01096    // fitter settings
01097    fIterations->Connect("ReturnPressed()", "TFitEditor", this, "DoMaxIterations()");
01098    
01099    // print options
01100    fOptDefault->Connect("Toggled(Bool_t)","TFitEditor",this,"DoPrintOpt(Bool_t)");
01101    fOptVerbose->Connect("Toggled(Bool_t)","TFitEditor",this,"DoPrintOpt(Bool_t)");
01102    fOptQuiet->Connect("Toggled(Bool_t)","TFitEditor",this,"DoPrintOpt(Bool_t)");
01103 
01104 }
01105 
01106 //______________________________________________________________________________
01107 void TFitEditor::DisconnectSlots()
01108 {
01109    // Disconnect GUI signals from fit panel slots.
01110 
01111    Disconnect("CloseWindow()");
01112 
01113    fFuncList->Disconnect("Selected(Int_t)");
01114    fEnteredFunc->Disconnect("ReturnPressed()");
01115    fSetParam->Disconnect("Clicked()");
01116    fAdd->Disconnect("Toggled(Bool_t)");
01117 
01118    // fit options
01119    fAllWeights1->Disconnect("Toggled(Bool_t)");
01120    fEmptyBinsWghts1->Disconnect("Toggled(Bool_t)");
01121 
01122    // linear fit
01123    fLinearFit->Disconnect("Toggled(Bool_t)");
01124    fNoChi2->Disconnect("Toggled(Bool_t)");
01125 
01126    // draw options
01127    fNoStoreDrawing->Disconnect("Toggled(Bool_t)");
01128 
01129    // fit, reset, close buttons
01130    fFitButton->Disconnect("Clicked()");
01131    fResetButton->Disconnect("Clicked()");
01132    
01133    // other methods
01134    fUserButton->Disconnect("Clicked()");
01135    fDrawAdvanced->Disconnect("Clicked()");
01136 
01137    if (fType != kObjectTree) {
01138       fSliderX->Disconnect("PositionChanged()");
01139       fSliderXMax->Disconnect("ValueChanged(Long_t)");
01140       fSliderXMin->Disconnect("ValueChanged(Long_t)");
01141    }
01142    if (fDim > 1) {
01143       fSliderY->Disconnect("PositionChanged()");
01144       fSliderYMax->Disconnect("ValueChanged(Long_t)");
01145       fSliderYMin->Disconnect("ValueChanged(Long_t)");
01146    }
01147    if (fDim > 2) 
01148       fSliderZ->Disconnect("PositionChanged()");
01149    
01150    // slots related to 'Minimization' tab
01151    fLibMinuit->Disconnect("Toggled(Bool_t)");
01152    fLibMinuit2->Disconnect("Toggled(Bool_t)");
01153    fLibFumili->Disconnect("Toggled(Bool_t)");
01154    fLibGSL->Disconnect("Toggled(Bool_t)");
01155    fLibGenetics->Disconnect("Toggled(Bool_t)");
01156 
01157    // minimization method
01158    fMinMethodList->Disconnect("Selected(Int_t)");
01159    
01160    // fitter settings
01161    fIterations->Disconnect("ReturnPressed()");
01162 
01163    // print options
01164    fOptDefault->Disconnect("Toggled(Bool_t)");
01165    fOptVerbose->Disconnect("Toggled(Bool_t)");
01166    fOptQuiet->Disconnect("Toggled(Bool_t)");
01167 
01168 }
01169 
01170 //______________________________________________________________________________
01171 void TFitEditor::SetCanvas(TCanvas * /*newcan*/)
01172 {
01173    // Connect to another canvas.
01174 
01175    // The next line is commented because it is stablishing a
01176    // connection with the particular canvas, while right the following
01177    // line will connect all the canvas in a general way.
01178 
01179    // It would also make the fitpanel crash if there is no object
01180    // defined to be fitted in the construction (as a side effect of
01181    // it).
01182 
01183 //    newcan->Connect("Selected(TVirtualPad*,TObject*,Int_t)", "TFitEditor",
01184 //                    this, "SetFitObject(TVirtualPad *, TObject *, Int_t)");
01185 
01186    TQObject::Connect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)", 
01187                      "TFitEditor",this, 
01188                      "SetFitObject(TVirtualPad *, TObject *, Int_t)");
01189    TQObject::Connect("TCanvas", "Closed()", "TFitEditor", this, "DoNoSelection()");
01190 }
01191 
01192 //______________________________________________________________________________
01193 void TFitEditor::Hide()
01194 {
01195    // Hide the fit panel and set it to non-active state. 
01196 
01197    if (fgFitDialog) {
01198       fgFitDialog->UnmapWindow();
01199    }
01200    if (fParentPad) {
01201       fParentPad->Disconnect("RangeAxisChanged()");
01202       DoReset();
01203    }
01204    fParentPad = 0;
01205    fFitObject = 0;
01206    gROOT->GetListOfCleanups()->Remove(this);
01207 }
01208 
01209 //______________________________________________________________________________
01210 void TFitEditor::Show(TVirtualPad* pad, TObject *obj)
01211 {
01212    // Show the fit panel (possible only via context menu).
01213 
01214    if (!gROOT->GetListOfCleanups()->FindObject(this))
01215       gROOT->GetListOfCleanups()->Add(this);   
01216 
01217    if (!fgFitDialog->IsMapped()) {
01218       fgFitDialog->MapWindow();
01219       gVirtualX->RaiseWindow(GetId());
01220    }
01221    fParentPad = static_cast<TPad*>(pad);
01222    SetCanvas(pad->GetCanvas());
01223    SetFitObject(pad, obj, kButton1Down);
01224 }
01225 
01226 //______________________________________________________________________________
01227 void TFitEditor::CloseWindow()
01228 {
01229    // Close fit panel window.
01230 
01231    Hide();
01232 }
01233 
01234 //______________________________________________________________________________
01235 // TFitEditor *&TFitEditor::GetFP()
01236 // {
01237 //    // Static: return main fit panel
01238 //    return fgFitDialog;
01239 // }
01240 
01241 //______________________________________________________________________________
01242 void TFitEditor::Terminate()
01243 {
01244    //  Called to delete the fit panel. 
01245 
01246    TQObject::Disconnect("TCanvas", "Closed()");
01247    delete fgFitDialog;
01248    fgFitDialog = 0;
01249 }
01250 
01251 //______________________________________________________________________________
01252 void TFitEditor::UpdateGUI()
01253 {
01254    //  Set the fit panel GUI according to the selected object. 
01255 
01256    if (!fFitObject) return;
01257 
01258    DrawSelection(true);
01259 
01260    if ( fType == kObjectTree )
01261       // Don't do anything with the sliders, as they work with TAxis
01262       // that are not defined for the TTree
01263       return;
01264 
01265    // sliders
01266    if (fType != kObjectTree) { // This is as fDim > 0
01267       TH1* hist = 0;
01268       switch (fType) {
01269          case kObjectHisto:
01270             hist = (TH1*)fFitObject;
01271             break;
01272 
01273          case kObjectGraph:
01274             hist = ((TGraph*)fFitObject)->GetHistogram();
01275             break;
01276 
01277          case kObjectMultiGraph:
01278             hist = ((TMultiGraph*)fFitObject)->GetHistogram();
01279             break;
01280 
01281          case kObjectGraph2D:
01282             hist = ((TGraph2D*)fFitObject)->GetHistogram("empty");
01283             break;
01284 
01285          case kObjectHStack: 
01286             hist = (TH1 *)((THStack *)fFitObject)->GetHists()->First();
01287 
01288          case kObjectTree:
01289          default:
01290             break;
01291       }
01292       
01293 
01294       if (!hist) {
01295          Error("UpdateGUI","No hist is present - this should not happen, please report."
01296                "The FitPanel might be in an inconsistent state");
01297          //assert(hist);
01298          return;
01299       }
01300 
01301       fSliderX->Disconnect("PositionChanged()");
01302       fSliderXMin->Disconnect("ValueChanged()");
01303       fSliderXMax->Disconnect("ValueChanged()");
01304 
01305       if (!fSliderXParent->IsMapped())
01306          fSliderXParent->MapWindow();
01307 
01308       fXaxis = hist->GetXaxis();
01309       fYaxis = hist->GetYaxis();
01310       fZaxis = hist->GetZaxis();
01311       Int_t ixrange = fXaxis->GetNbins();
01312       Int_t ixmin = fXaxis->GetFirst();
01313       Int_t ixmax = fXaxis->GetLast();
01314 
01315       if (ixmin > 1 || ixmax < ixrange) {
01316         fSliderX->SetRange(ixmin,ixmax);
01317         fSliderX->SetPosition(ixmin, ixmax);
01318       } else {
01319         fSliderX->SetRange(1,ixrange);
01320         fSliderX->SetPosition(ixmin,ixmax);
01321       }
01322       
01323       fSliderX->SetScale(5);
01324 
01325       fSliderXMin->SetLimits(TGNumberFormat::kNELLimitMinMax,
01326                              fXaxis->GetBinLowEdge( static_cast<Int_t>( fSliderX->GetMinPosition() ) ), 
01327                              fXaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderX->GetMaxPosition() ) ));
01328       fSliderXMin->SetNumber( fXaxis->GetBinLowEdge( static_cast<Int_t>( fSliderX->GetMinPosition() ) ));
01329       fSliderXMax->SetLimits(TGNumberFormat::kNELLimitMinMax,
01330                              fXaxis->GetBinLowEdge( static_cast<Int_t>( fSliderX->GetMinPosition() ) ), 
01331                              fXaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderX->GetMaxPosition() ) ));
01332       fSliderXMax->SetNumber( fXaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderX->GetMaxPosition() ) ));
01333 
01334       fSliderX->Connect("PositionChanged()","TFitEditor",this, "DoSliderXMoved()");
01335       fSliderXMax->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderXChanged()");
01336       fSliderXMin->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderXChanged()");
01337    }
01338 
01339    if (fDim > 1) {
01340       fSliderY->Disconnect("PositionChanged()");
01341       fSliderYMin->Disconnect("ValueChanged()");
01342       fSliderYMax->Disconnect("ValueChanged()");
01343 
01344       if (!fSliderYParent->IsMapped())
01345          fSliderYParent->MapWindow();
01346       if (fSliderZParent->IsMapped())
01347          fSliderZParent->UnmapWindow();
01348 
01349       Int_t iymin = 0, iymax = 0, iyrange = 0;
01350       switch (fType) {
01351          case kObjectHisto: 
01352          case kObjectGraph2D:
01353          case kObjectHStack: 
01354             iyrange = fYaxis->GetNbins();
01355             iymin = fYaxis->GetFirst();
01356             iymax = fYaxis->GetLast();
01357             break;
01358          
01359          case kObjectGraph: 
01360          case kObjectMultiGraph: 
01361          case kObjectTree:
01362          default:
01363             //not implemented
01364             break;
01365       }
01366 
01367       if (iymin > 1 || iymax < iyrange) {
01368         fSliderY->SetRange(iymin,iymax);
01369         fSliderY->SetPosition(iymin, iymax);
01370       } else {
01371         fSliderY->SetRange(1,iyrange);
01372         fSliderY->SetPosition(iymin,iymax);
01373       }
01374 
01375       fSliderY->SetScale(5);
01376 
01377       fSliderYMin->SetLimits(TGNumberFormat::kNELLimitMinMax,
01378                              fYaxis->GetBinLowEdge( static_cast<Int_t>( fSliderY->GetMinPosition() ) ), 
01379                              fYaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderY->GetMaxPosition() ) ));
01380       fSliderYMin->SetNumber(fYaxis->GetBinLowEdge( static_cast<Int_t>( fSliderY->GetMinPosition() ) ));
01381       fSliderYMax->SetLimits(TGNumberFormat::kNELLimitMinMax,
01382                              fYaxis->GetBinLowEdge( static_cast<Int_t>( fSliderY->GetMinPosition() ) ), 
01383                              fYaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderY->GetMaxPosition() ) ));
01384       fSliderYMax->SetNumber( fYaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderY->GetMaxPosition() ) ));
01385 
01386       fSliderY->Connect("PositionChanged()","TFitEditor",this, "DoSliderYMoved()");
01387       fSliderYMax->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderYChanged()");
01388       fSliderYMin->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderYChanged()");
01389    }
01390 
01391    
01392    if (fDim > 2) {
01393       fSliderZ->Disconnect("PositionChanged()");
01394 
01395       if (!fSliderZParent->IsMapped())
01396          fSliderZParent->MapWindow();
01397 
01398       Int_t izmin = 0, izmax = 0, izrange = 0;
01399       switch (fType) {
01400          case kObjectHStack:
01401          case kObjectHisto:
01402             izrange = fZaxis->GetNbins();
01403             izmin = fZaxis->GetFirst();
01404             izmax = fZaxis->GetLast();
01405             break;
01406 
01407          case kObjectGraph:
01408          case kObjectGraph2D:
01409          case kObjectMultiGraph:
01410          case kObjectTree:
01411          default:
01412             //not implemented
01413             break;
01414       }
01415 
01416       if (izmin > 1 || izmax < izrange) {
01417         fSliderZ->SetRange(izmin,izmax);
01418         fSliderZ->SetPosition(izmin, izmax);
01419       } else {
01420         fSliderZ->SetRange(1,izrange);
01421         fSliderZ->SetPosition(izmin,izmax);
01422       }
01423 
01424       fSliderZ->SetScale(5);
01425       fSliderZ->Connect("PositionChanged()","TFitEditor",this, "DoSliderZMoved()");
01426    }
01427 }
01428 
01429 //______________________________________________________________________________
01430 void TFitEditor::SetFitObject(TVirtualPad *pad, TObject *obj, Int_t event)
01431 {
01432    // Slot called when the user clicks on an object inside a canvas. 
01433    // Updates pointers to the parent pad and the selected object
01434    // for fitting (if suitable).
01435 
01436    if (event != kButton1Down) return;
01437 
01438    if ( !obj ) {
01439       DoNoSelection();
01440       return;
01441    }
01442    
01443    // is obj suitable for fitting?
01444    if (!SetObjectType(obj)) return;
01445 
01446    fParentPad = pad;
01447    fFitObject = obj;
01448    ShowObjectName(obj);
01449    UpdateGUI();
01450 
01451    ConnectSlots();
01452    
01453    TF1* fitFunc = HasFitFunction();
01454 
01455    if (fitFunc) {
01456       //fFuncPars = FuncParams_t( fitFunc->GetNpar() );
01457       GetParameters(fFuncPars, fitFunc);
01458 
01459       TString tmpStr = fitFunc->GetExpFormula();
01460       TGLBEntry *en = 0;
01461       // If the function comes from a C raw function.
01462       if ( tmpStr.Length() == 0 )
01463       {
01464          // Show the name of the function
01465          fEnteredFunc->SetText(fitFunc->GetName());
01466          en= fFuncList->FindEntry(fitFunc->GetName());
01467          // Don't allow edition!
01468          SetEditable(kFALSE);
01469       }
01470       // otherwise, it's got a formula
01471       else
01472       {
01473          // Show the formula
01474          fEnteredFunc->SetText(fitFunc->GetExpFormula().Data());
01475          en= fFuncList->FindEntry(fitFunc->GetExpFormula().Data());
01476          SetEditable(kTRUE);
01477       }
01478       // Select the proper entry in the function list
01479       if (en) fFuncList->Select(en->EntryId());
01480    } else { // if there is no fit function in the object
01481       // Use the selected function in fFuncList
01482       TGTextLBEntry *te = (TGTextLBEntry *)fFuncList->GetSelectedEntry();
01483       // Add the text to fEnteredFunc
01484       if (te && fNone->GetState() == kButtonDown)
01485          fEnteredFunc->SetText(te->GetTitle());
01486       else if (te && fAdd->GetState() == kButtonDown) {
01487          TString tmpStr = fEnteredFunc->GetText();
01488          tmpStr += '+';
01489          tmpStr +=te->GetTitle();
01490          fEnteredFunc->SetText(tmpStr);
01491       } else if ( !te )
01492          // If there is no space, an error message is shown:
01493          // Error in <TString::AssertElement>: out of bounds: i = -1, Length = 0
01494          // If there is no function selected, then put nothing.
01495          fEnteredFunc->SetText(" ");
01496    }
01497    fEnteredFunc->SelectAll();
01498 
01499 
01500    // Update the information about the selected object.
01501    if (fSetParam->GetState() == kButtonDisabled)
01502       fSetParam->SetEnabled(kTRUE);
01503    if (fFitButton->GetState() == kButtonDisabled)
01504       fFitButton->SetEnabled(kTRUE);
01505    if (fResetButton->GetState() == kButtonDisabled)
01506       fResetButton->SetEnabled(kTRUE);
01507    DoLinearFit();
01508 }
01509 
01510 //______________________________________________________________________________
01511 void TFitEditor::DoNoSelection()
01512 {
01513    // Slot called when users close a TCanvas or when the user select
01514    // no object.
01515 
01516    if (gROOT->GetListOfCanvases()->IsEmpty()) {
01517       Terminate();
01518       return;
01519    }
01520    
01521    // Minimize user interaction until an object is selected
01522    DisconnectSlots();
01523    fParentPad = 0;
01524    fFitObject = 0;
01525    fStatusBar->SetText("No selection",0);
01526    fDataSet->Select(kFP_NOSEL, kFALSE);
01527    Layout();
01528 
01529    fSetParam->SetEnabled(kFALSE);
01530    fFitButton->SetEnabled(kFALSE);
01531    fResetButton->SetEnabled(kFALSE);
01532    fDrawAdvanced->SetState(kButtonDisabled);
01533 }
01534 
01535 //______________________________________________________________________________
01536 void TFitEditor::RecursiveRemove(TObject* obj)
01537 {
01538    // When obj is deleted, clear fFitObject if fFitObject = obj.
01539 
01540    if (obj == fFitObject) {
01541       fFitObject = 0;
01542       DisconnectSlots();
01543       fStatusBar->SetText("No selection",0);
01544       fDataSet->Select(kFP_NOSEL, kFALSE);
01545       Layout();
01546 
01547       fFitButton->SetEnabled(kFALSE);
01548       fResetButton->SetEnabled(kFALSE);
01549       fSetParam->SetEnabled(kFALSE);
01550       
01551       TQObject::Connect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)", 
01552                         "TFitEditor",this, 
01553                         "SetFitObject(TVirtualPad *, TObject *, Int_t)");
01554       TQObject::Connect("TCanvas", "Closed()", "TFitEditor", this, 
01555                         "DoNoSelection()");
01556 
01557       DoUpdate();
01558       return;
01559    }
01560    if (obj == fParentPad) {
01561       fFitObject = 0;
01562       fParentPad = 0;
01563       DisconnectSlots();
01564       fStatusBar->SetText("No selection",0);
01565       fDataSet->Select(kFP_NOSEL, kFALSE);
01566       Layout();
01567 
01568       fFitButton->SetEnabled(kFALSE);
01569       fResetButton->SetEnabled(kFALSE);
01570       fSetParam->SetEnabled(kFALSE);
01571    }
01572 }
01573 
01574 //______________________________________________________________________________
01575 void TFitEditor::FillFunctionList(Int_t)
01576 {
01577    // Fills the list of functions depending on the type of fit
01578    // selected.
01579 
01580    fFuncList->RemoveAll();
01581    // Case when the user has selected predefined functions in 1D.
01582    if ( fTypeFit->GetSelected() == kFP_PRED1D && fDim <= 1 ) {
01583       // Fill function list combo box.
01584       fFuncList->AddEntry("gaus" ,  kFP_GAUS);
01585       fFuncList->AddEntry("gausn",  kFP_GAUSN);
01586       fFuncList->AddEntry("expo",   kFP_EXPO);
01587       fFuncList->AddEntry("landau", kFP_LAND);
01588       fFuncList->AddEntry("landaun",kFP_LANDN);
01589       fFuncList->AddEntry("pol0",   kFP_POL0);
01590       fFuncList->AddEntry("pol1",   kFP_POL1);
01591       fFuncList->AddEntry("pol2",   kFP_POL2);
01592       fFuncList->AddEntry("pol3",   kFP_POL3);
01593       fFuncList->AddEntry("pol4",   kFP_POL4);
01594       fFuncList->AddEntry("pol5",   kFP_POL5);
01595       fFuncList->AddEntry("pol6",   kFP_POL6);
01596       fFuncList->AddEntry("pol7",   kFP_POL7);
01597       fFuncList->AddEntry("pol8",   kFP_POL8);
01598       fFuncList->AddEntry("pol9",   kFP_POL9);
01599       fFuncList->AddEntry("user",   kFP_USER);
01600 
01601       // Need to be setted this way, otherwise when the functions
01602       // are removed, the list doesn't show them.
01603       TGListBox *lb = fFuncList->GetListBox();
01604       lb->Resize(lb->GetWidth(), 200);
01605 
01606       // Select Gaus1D by default
01607       fFuncList->Select(kFP_GAUS);
01608    }
01609    // Case for predefined 2D functions
01610    else if ( fTypeFit->GetSelected() == kFP_PRED2D && fDim == 2 ) {
01611       fFuncList->AddEntry("xygaus", kFP_XYGAUS);
01612       fFuncList->AddEntry("xyexpo", kFP_XYEXP);
01613       fFuncList->AddEntry("xylandau", kFP_XYLAN);
01614       fFuncList->AddEntry("xylandaun", kFP_XYLANN);
01615 
01616       // Need to be setted this way, otherwise when the functions
01617       // are removed, the list doesn't show them.x
01618       TGListBox *lb = fFuncList->GetListBox(); 
01619       lb->Resize(lb->GetWidth(), 200);
01620 
01621       // Select Gaus2D by default
01622       fFuncList->Select(kFP_XYGAUS);
01623    }
01624    // Case for user defined functions. References to these functions
01625    // are kept by the fitpanel, so the information is gathered from
01626    // there.
01627    else if ( fTypeFit->GetSelected() == kFP_UFUNC ) {
01628       Int_t newid = kFP_ALTFUNC;
01629 
01630       // Add system functions
01631       for ( fSystemFuncIter it = fSystemFuncs.begin();
01632             it != fSystemFuncs.end(); ++it ) {
01633          TF1* f = (*it);
01634          // Don't include system functions that has been previously
01635          // used to fit, as those are included under the kFP_PREVFIT
01636          // section.
01637          if ( strncmp(f->GetName(), "PrevFit", 7) != 0 ) {
01638             // If the dimension of the object coincides with the
01639             // dimension of the function, then include the function in
01640             // the list. It will also include de function if the
01641             // dimension of the object is 0 (i.e. a multivariable
01642             // TTree) as it is currently imposible to know how many
01643             // dimensions a TF1 coming from a C raw function has.
01644             if ( f->GetNdim() == fDim || fDim == 0) {
01645                fFuncList->AddEntry(f->GetName(), newid++); 
01646             }
01647          }
01648       }
01649 
01650       // If no function was added
01651       if ( newid != kFP_ALTFUNC )
01652          fFuncList->Select(newid-1);
01653       else if( fDim == 1 ) {
01654          // Select predefined 1D functions for 1D objects
01655          fTypeFit->Select(kFP_PRED1D, kTRUE);
01656       } else if( fDim == 2 ) {
01657          // Select predefined 2D functions for 2D objects
01658          fTypeFit->Select(kFP_PRED2D, kTRUE);
01659       }
01660    } 
01661    // Case for previously used functions.
01662    else if ( fTypeFit->GetSelected() == kFP_PREVFIT ) {
01663       Int_t newid = kFP_ALTFUNC;
01664       
01665       // Look only for those functions used in the selected object
01666       pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(fFitObject);
01667       // Then go over all those functions and add them to the list
01668       for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
01669          fFuncList->AddEntry(it->second->GetName(), newid++);
01670       }
01671 
01672       // If no functions were added.
01673       if ( newid == kFP_ALTFUNC ) {
01674          // Remove the entry previous fit from fTypeFit
01675          fTypeFit->RemoveEntry(kFP_PREVFIT);
01676          if( fDim == 1 )
01677             // Select predefined 1D functions for 1D objects
01678             fTypeFit->Select(kFP_PRED1D, kTRUE);
01679          else if ( fDim == 2 )
01680             // Select predefined 2D functions for 2D objects
01681             fTypeFit->Select(kFP_PRED2D, kTRUE);
01682          else
01683             // For more than 2 dimensions, select the user functions.
01684             fTypeFit->Select(kFP_UFUNC, kTRUE);
01685       }
01686       else
01687          // If there is there are previously used functions, select
01688          // the last one inserted.
01689          fFuncList->Select(newid-1, kTRUE);
01690    }
01691 }
01692 
01693 //______________________________________________________________________________
01694 void TFitEditor::FillMinMethodList(Int_t)
01695 {
01696    // Fills the list of methods depending on the minimization library
01697    // selected.
01698 
01699    fMinMethodList->RemoveAll();
01700    
01701    if ( fLibMinuit->GetState() == kButtonDown ) 
01702    {
01703       fMinMethodList->AddEntry("MIGRAD" ,       kFP_MIGRAD);
01704       fMinMethodList->AddEntry("SIMPLEX" ,      kFP_SIMPLX);
01705       fMinMethodList->AddEntry("SCAN" ,         kFP_SCAN);
01706       fMinMethodList->AddEntry("Combination" ,  kFP_COMBINATION);
01707       fMinMethodList->Select(kFP_MIGRAD, kFALSE);
01708       fStatusBar->SetText("MIGRAD",2);
01709    } else if ( fLibFumili->GetState() == kButtonDown ) 
01710    {
01711       fMinMethodList->AddEntry("FUMILI" , kFP_FUMILI);
01712       fMinMethodList->Select(kFP_FUMILI, kFALSE);
01713       fStatusBar->SetText("FUMILI",2);
01714    } else if ( fLibGSL->GetState() == kButtonDown ) 
01715    {
01716       fMinMethodList->AddEntry("Fletcher-Reeves conjugate gradient" , kFP_GSLFR);
01717       fMinMethodList->AddEntry("Polak-Ribiere conjugate gradient" ,   kFP_GSLPR);
01718       fMinMethodList->AddEntry("BFGS conjugate gradient" ,            kFP_BFGS);
01719       fMinMethodList->AddEntry("BFGS conjugate gradient (Version 2)", kFP_BFGS2);
01720       fMinMethodList->AddEntry("Levenberg-Marquardt" ,                kFP_GSLLM);
01721       fMinMethodList->AddEntry("Simulated Annealing" ,                kFP_GSLSA);
01722       fMinMethodList->Select(kFP_GSLFR, kFALSE);
01723       fStatusBar->SetText("CONJFR",2);
01724    } else if ( fLibGenetics->GetState() == kButtonDown ) 
01725    {
01726       if ( gPluginMgr->FindHandler("ROOT::Math::Minimizer","GAlibMin") ) {
01727          fMinMethodList->AddEntry("GA Lib Genetic Algorithm" , kFP_GALIB);
01728          fMinMethodList->Select(kFP_GALIB, kFALSE);
01729       } else if (gPluginMgr->FindHandler("ROOT::Math::Minimizer","Genetic")) {
01730          fMinMethodList->AddEntry("TMVA Genetic Algorithm" ,   kFP_TMVAGA);
01731          fMinMethodList->Select(kFP_TMVAGA, kFALSE);
01732       }
01733    } else // if ( fLibMinuit2->GetState() == kButtonDown )
01734    {
01735       fMinMethodList->AddEntry("MIGRAD" ,       kFP_MIGRAD);
01736       fMinMethodList->AddEntry("SIMPLEX" ,      kFP_SIMPLX);
01737       fMinMethodList->AddEntry("FUMILI" ,       kFP_FUMILI);
01738       fMinMethodList->AddEntry("SCAN" ,         kFP_SCAN);
01739       fMinMethodList->AddEntry("Combination" ,  kFP_COMBINATION);
01740       fMinMethodList->Select(kFP_MIGRAD, kFALSE);
01741       fStatusBar->SetText("MIGRAD",2);
01742    }
01743 }
01744 
01745 void SearchCanvases(TSeqCollection* canvases, vector<TObject*>& objects)
01746 {
01747    // Auxiliary function to recursively search for objects inside the
01748    // current canvases.
01749 
01750    TIter canvasIter(canvases);
01751    // Iterate over all the canvases in canvases.
01752    while(TObject* obj = (TObject*) canvasIter()) {
01753       // If the object is another canvas, call this function
01754       // recursively.
01755       if ( TPad* can = dynamic_cast<TPad*>(obj))
01756          SearchCanvases(can->GetListOfPrimitives(), objects);
01757       // Otherwhise, if it's a recognised object, add it to the vector
01758       else if (    dynamic_cast<TH1*>(obj)
01759                 || dynamic_cast<TGraph*>(obj)
01760                 || dynamic_cast<TGraph2D*>(obj)
01761                 || dynamic_cast<TMultiGraph*>(obj)
01762                 || dynamic_cast<THStack*>(obj)
01763                 || dynamic_cast<TTree*>(obj) ) {
01764          bool insertNew = true;
01765          // Be careful no to insert the same element twice.
01766          for ( vector<TObject*>::iterator i = objects.begin(); i != objects.end(); ++i )
01767             if ( (*i) == obj ) {
01768                insertNew = false;
01769                break;
01770             }
01771          // If the object is not already in the vector, then insert
01772          // it.
01773          if ( insertNew ) objects.push_back(obj);
01774       }
01775    }
01776 }
01777 
01778 //______________________________________________________________________________
01779 void TFitEditor::FillDataSetList()
01780 {
01781    // Create a combo box with all the possible objects to be fitted.
01782 
01783    // Get the title of the entry selected, so that we can select it
01784    // again once the fDataSet has been refilled.
01785    TGTextLBEntry * entry = (TGTextLBEntry*) fDataSet->GetSelectedEntry();
01786    TString selEntryStr;
01787    if ( entry ) {
01788       selEntryStr = entry->GetTitle();
01789    }
01790 
01791    // Remove all the elements
01792    fDataSet->RemoveAll();
01793    vector<TObject*> objects;
01794 
01795    // Get all the objects registered in gDirectory
01796    TIter next(gDirectory->GetList());
01797    TObject* obj = NULL;
01798    while ( (obj = (TObject*) next()) ) {
01799       // But only if they are of a type recognized by the FitPanel
01800       if ( dynamic_cast<TH1*>(obj) || 
01801            dynamic_cast<TGraph2D*>(obj) ||
01802            dynamic_cast<TTree*>(obj) ) {
01803          objects.push_back(obj);
01804       }
01805    }
01806 
01807    // Look for all the drawn objects. The method will take care the
01808    // same objects are not inserted twice.
01809    SearchCanvases(gROOT->GetListOfCanvases(), objects);
01810 
01811    // Add all the objects stored in the vector
01812    int selected = kFP_NOSEL;
01813    // Add the No selection.
01814    Int_t newid = kFP_NOSEL;
01815    fDataSet->AddEntry("No Selection", newid++);
01816    for ( vector<TObject*>::iterator i = objects.begin(); i != objects.end(); ++i ) {
01817       // Insert the name as the class name followed by the name of the
01818       // object.
01819       TString name = (*i)->ClassName(); name.Append("::"); name.Append((*i)->GetName());
01820       // Check whether the names are the same!
01821       if ( selEntryStr && name == selEntryStr )
01822          selected = newid;
01823       fDataSet->AddEntry(name, newid++);
01824    }
01825 
01826    // If there was an entry selected (which should be always the case
01827    // except the first time this method is executed), then make it the
01828    // selected one again.
01829    if (entry) {
01830       fDataSet->Select(selected);
01831    }
01832 }
01833 
01834 //______________________________________________________________________________
01835 TGComboBox* TFitEditor::BuildMethodList(TGFrame* parent, Int_t id)
01836 {
01837    // Create method list in a combo box.
01838 
01839    TGComboBox *c = new TGComboBox(parent, id);
01840    c->AddEntry("Chi-square", kFP_MCHIS);
01841    c->AddEntry("Binned Likelihood", kFP_MBINL);
01842    c->AddEntry("Unbinned Likelihood", kFP_MUBIN);
01843    //c->AddEntry("User", kFP_MUSER);                //for later use
01844    c->Select(kFP_MCHIS);
01845    return c;
01846 }
01847 
01848 //______________________________________________________________________________
01849 void TFitEditor::DoAdvancedOptions()
01850 {
01851    // Slot connected to advanced option button (opens a dialog).
01852 
01853    new TAdvancedGraphicsDialog( fClient->GetRoot(), GetMainFrame());
01854 }
01855 
01856 //______________________________________________________________________________
01857 void TFitEditor::DoEmptyBinsAllWeights1()
01858 {
01859    // Slot connected to 'include emtry bins and forse all weights to 1' setting.
01860 
01861    if (fEmptyBinsWghts1->GetState() == kButtonDown)
01862       if (fAllWeights1->GetState() == kButtonDown)
01863          fAllWeights1->SetState(kButtonUp, kTRUE);
01864 }
01865 
01866 //______________________________________________________________________________
01867 void TFitEditor::DoUseFuncRange()
01868 {
01869    
01870    if ( fUseRange->GetState() == kButtonDown ) {
01871       if (fNone->GetState() == kButtonDown || fNone->GetState() == kButtonDisabled) {
01872          // Get the function
01873          TF1* tmpTF1 = FindFunction();
01874          if ( !tmpTF1 ) {
01875             if (GetFitObjectListOfFunctions()) {
01876                TGTextLBEntry *te = (TGTextLBEntry *)fFuncList->GetSelectedEntry();
01877                tmpTF1 = (TF1*) GetFitObjectListOfFunctions()->FindObject( te->GetTitle() );
01878             }
01879          }
01880          // If the function has been retrieved, i.e. is a registered function.
01881          if ( tmpTF1 ) {
01882             Double_t xmin, ymin, zmin, xmax, ymax, zmax;
01883             // Get the range
01884             tmpTF1->GetRange(xmin, ymin, zmin, xmax, ymax, zmax);
01885             // And set the sliders
01886             if ( fType != kObjectTree ) {
01887                fSliderXMin->SetNumber( xmin );
01888                fSliderXMax->SetNumber( xmax );
01889                DoNumericSliderXChanged();
01890                if ( fDim > 1 ) {
01891                   fSliderYMin->SetNumber( ymin );
01892                   fSliderYMax->SetNumber( ymax );
01893                   DoNumericSliderYChanged();
01894                }
01895             }
01896          }
01897       }
01898       fUseRange->SetState(kButtonDown);
01899    }
01900 }
01901 
01902 //______________________________________________________________________________
01903 void TFitEditor::DoAllWeights1()
01904 {
01905    // Slot connected to 'set all weights to 1' setting.
01906 
01907    if (fAllWeights1->GetState() == kButtonDown)
01908       if (fEmptyBinsWghts1->GetState() == kButtonDown)
01909          fEmptyBinsWghts1->SetState(kButtonUp, kTRUE);
01910 }
01911 
01912 //______________________________________________________________________________
01913 void TFitEditor::DoClose()
01914 {
01915    // Close the fit panel.
01916 
01917    Hide();
01918 }
01919 
01920 //______________________________________________________________________________
01921 void TFitEditor::DoUpdate()
01922 {
01923    // Easy here!
01924    GetFunctionsFromSystem();
01925    FillDataSetList();
01926 }
01927 
01928 //______________________________________________________________________________
01929 void TFitEditor::DoFit()
01930 {
01931    // Perform a fit with current parameters' settings.
01932 
01933    if (!fFitObject) return;
01934    //if (!fParentPad) return;
01935 
01936    // If fNone->GetState() == kButtonDisabled means the function is
01937    // not editable, i.e. it comes from a raw C function. So in this
01938    // case, it is editable and we have to check wheather the formula
01939    // is well built.
01940    if ( fNone->GetState() != kButtonDisabled && CheckFunctionString(fEnteredFunc->GetText()) )
01941    {
01942       // If not, then show an error message and leave.
01943       new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
01944                    "Error...", "DoFit\nVerify the entered function string!",
01945                    kMBIconStop,kMBOk, 0);
01946       return;
01947    }
01948 
01949    // Set the button so that the user cannot use it while fitting, set
01950    // the mouse to watch type and so on.
01951    fFitButton->SetState(kButtonEngaged);
01952    if (gPad) gPad->GetVirtCanvas()->SetCursor(kWatch);
01953    gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kWatch));
01954 
01955    TVirtualPad *save = 0;
01956    if ( fParentPad ) {
01957       fParentPad->Disconnect("RangeAxisChanged()");
01958       save = gPad;
01959       gPad = fParentPad;
01960       fParentPad->cd();
01961 
01962       fParentPad->GetCanvas()->SetCursor(kWatch);
01963    }
01964 
01965    // Get the ranges from the sliders
01966    ROOT::Fit::DataRange drange; 
01967    GetRanges(drange);
01968 
01969    // Create a static pointer to fitFunc. Every second call to the
01970    // DoFit method, the old fitFunc is deleted. We need not to delete
01971    // the function after the fitting in case we want to do Advaced
01972    // graphics. The VirtualFitter need the function to be alived. One
01973    // problem, after the last fit the function is never deleted, but
01974    // ROOT's garbage collector will do the job for us.
01975    static TF1 *fitFunc = 0;
01976    if ( fitFunc )
01977       delete fitFunc;
01978    fitFunc = GetFitFunction();
01979    // This assert
01980    if (!fitFunc) { 
01981       Error("DoFit","This should have never happend, the fitfunc pointer is NULL! - Please Report" );
01982       return;
01983    }
01984    
01985    // set parameters from panel in function
01986    SetParameters(fFuncPars, fitFunc);
01987    // Get the options stored in the GUI elements.
01988    ROOT::Math::MinimizerOptions mopts;
01989    Foption_t fitOpts;
01990    TString strDrawOpts;
01991    RetrieveOptions(fitOpts, strDrawOpts, mopts, fitFunc->GetNpar());
01992 
01993    // Call the fit method, depending on the object to fit.
01994    switch (fType) {
01995       case kObjectHisto: {
01996          
01997          TH1 *hist = dynamic_cast<TH1*>(fFitObject);
01998          if (hist)
01999             ROOT::Fit::FitObject(hist, fitFunc, fitOpts, mopts, strDrawOpts, drange);
02000 
02001          break;
02002       }
02003       case kObjectGraph: {
02004 
02005          TGraph *gr = dynamic_cast<TGraph*>(fFitObject);
02006          if (gr)
02007             FitObject(gr, fitFunc, fitOpts, mopts, strDrawOpts, drange);
02008          break;
02009       }
02010       case kObjectMultiGraph: {
02011 
02012          TMultiGraph *mg = dynamic_cast<TMultiGraph*>(fFitObject);
02013          if (mg)
02014             FitObject(mg, fitFunc, fitOpts, mopts, strDrawOpts, drange);
02015 
02016          break;
02017       }
02018       case kObjectGraph2D: {
02019 
02020          TGraph2D *g2d = dynamic_cast<TGraph2D*>(fFitObject);
02021          if (g2d)
02022             FitObject(g2d, fitFunc, fitOpts, mopts, strDrawOpts, drange);
02023 
02024          break;
02025       }
02026       case kObjectHStack: {
02027          // N/A
02028          break;
02029       }
02030       case kObjectTree:  {
02031          // The three is a much more special case. The steps for
02032          // fitting have to be done manually here until they are
02033          // properly implemented within a FitObject method in
02034          // THFitImpl.cxx
02035 
02036          // Retrieve the variables and cuts selected from the current
02037          // tree.
02038          TString variables;
02039          TString cuts;
02040          GetTreeVarsAndCuts(fDataSet, variables, cuts);
02041 
02042          // This should be straight forward and the return should
02043          // never be called.
02044          TTree *tree = dynamic_cast<TTree*>(fFitObject);
02045          if ( !tree ) return;
02046 
02047          // These method calls are just to set up everything for the
02048          // fitting. It's taken from another script.
02049          gROOT->ls();
02050          tree->Draw(variables,cuts,"goff candle");
02051 
02052          TTreePlayer * player = (TTreePlayer*) tree->GetPlayer();
02053          if ( !player ) {
02054             Error("DoFit","Player reference is NULL"); 
02055             return; 
02056          }
02057 
02058          TSelectorDraw * selector = (TSelectorDraw* ) player->GetSelector(); 
02059          if ( !selector ) {
02060             Error("DoFit","Selector reference is NULL"); 
02061             return; 
02062          }
02063 
02064          // use pointer stored in the tree (not copy the data in)
02065          unsigned int ndim = player->GetDimension();
02066          if ( ndim == 0 ) {
02067             Error("DoFit","NDIM == 0"); 
02068             return; 
02069          }
02070 
02071          std::vector<double *> vlist; 
02072          for (unsigned int i = 0; i < ndim; ++i) {  
02073             double * v =  selector->GetVal(i);
02074             if (v != 0) vlist.push_back(v);
02075             else 
02076                std::cerr << "pointer for variable " << i << " is zero" << std::endl;
02077          } 
02078          if (vlist.size() != ndim) { 
02079             Error("DoFit","Vector is not complete"); 
02080             return; 
02081          }
02082          
02083          // fill the data 
02084          Long64_t nrows = player->GetSelectedRows();
02085          if ( !nrows ) {
02086             Error("DoFit","NROWS == 0"); 
02087             return; 
02088          }
02089 
02090          ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
02091          
02092          for ( int i = 0; i < std::min(int(fitdata->Size()),10); ++i) { 
02093             // print j coordinate 
02094             for (unsigned int j = 0; j < ndim; ++j) {  
02095                printf(" x_%d [%d] = %f  \n", j, i,*(fitdata->Coords(i)+j) );
02096             } 
02097             printf("\n");
02098          }
02099          
02100    
02101          //TVirtualFitter::SetDefaultFitter("Minuit");
02102          Foption_t fitOption; 
02103          ROOT::Math::MinimizerOptions minOption;
02104          fitOption.Verbose=1;
02105 
02106          // After all the set up is performed, then do the Fit!!
02107          ROOT::Fit::UnBinFit(fitdata, fitFunc, fitOption, minOption);
02108          
02109          break;
02110       }
02111    }
02112 
02113    // if SAME is set re-plot the function
02114    // useful in case histogram was drawn with HIST 
02115    //  and no function will be drawm)
02116    if (fDrawSame->GetState() == kButtonDown && fitFunc) 
02117       fitFunc->Draw("same");
02118 
02119 
02120    // update parameters value shown in dialog 
02121    //if (!fFuncPars) fFuncPars = new Double_t[fitFunc->GetNpar()][3];
02122    GetParameters(fFuncPars,fitFunc);
02123 
02124    // Save fit data for future use as a PrevFit function.
02125    TF1* tmpTF1 = static_cast<TF1*>( copyTF1(fitFunc) );
02126    ostringstream name;
02127    name << "PrevFit-" << fPrevFit.size() + 1;
02128    if ( strcmp(tmpTF1->GetName(), "PrevFitTMP") != 0 )
02129       name << "-" << tmpTF1->GetName();
02130    tmpTF1->SetName(name.str().c_str());
02131    fPrevFit.insert(FitFuncMap_t::value_type(fFitObject, tmpTF1));
02132    fSystemFuncs.push_back( copyTF1(tmpTF1) );
02133 
02134    float xmin, xmax, ymin, ymax, zmin, zmax;
02135    if ( fParentPad ) {
02136       fParentPad->Modified();
02137       // As the range is not changed, save the old values and restore
02138       // after the GUI has been updated.  It would be more elegant to
02139       // disconnect the signal from fParentPad, however, this doesn't
02140       // work for unknown reasons.
02141       if ( fType != kObjectTree ) fSliderX->GetPosition(xmin, xmax);
02142       if ( fDim > 1 ) fSliderY->GetPosition(ymin, ymax);
02143       if ( fDim > 2 ) fSliderZ->GetPosition(zmin, zmax);
02144       fParentPad->Update();
02145    }
02146 
02147    // In case the fit method draws something! Set the canvas!
02148    fParentPad = gPad;
02149    UpdateGUI();
02150 
02151    // Change the sliders if necessary.
02152    if ( fParentPad ) {
02153       if ( fType != kObjectTree ) { fSliderX->SetPosition(xmin, xmax); DoSliderXMoved(); }
02154       if ( fType != kObjectTree && fDim > 1 ) { fSliderY->SetPosition(ymin, ymax); DoSliderYMoved(); }
02155       if ( fType != kObjectTree && fDim > 2 ) { fSliderZ->SetPosition(zmin, zmax); DoSliderZMoved(); }
02156       fParentPad->GetCanvas()->SetCursor(kPointer);
02157       fParentPad->Connect("RangeAxisChanged()", "TFitEditor", this, "UpdateGUI()");
02158       
02159       if (save) gPad = save;
02160       if (fSetParam->GetState() == kButtonDisabled && 
02161           fLinearFit->GetState() == kButtonUp)
02162          fSetParam->SetState(kButtonUp);
02163    }
02164 
02165    // Restore the Fit button and mouse cursor to their proper state.
02166    if (gPad) gPad->GetVirtCanvas()->SetCursor(kPointer);
02167    gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
02168    fFitButton->SetState(kButtonUp);
02169 
02170    if ( !fTypeFit->FindEntry("Prev. Fit") )
02171       fTypeFit->InsertEntry("Prev. Fit",kFP_PREVFIT, kFP_UFUNC);
02172 
02173    fDrawAdvanced->SetState(kButtonUp);
02174 }
02175 
02176 //______________________________________________________________________________
02177 Int_t TFitEditor::CheckFunctionString(const char *fname)
02178 {
02179    // Check entered function string.
02180    Int_t rvalue = 0;
02181    if ( fDim == 1 || fDim == 0 ) {
02182       TF1 form("tmpCheck", fname);
02183       rvalue = form.Compile();
02184    } else if ( fDim == 2 ) {
02185       TF2 form("tmpCheck", fname);
02186       rvalue = form.Compile();
02187    } else if ( fDim == 3 ) {
02188       TF3 form("tmpCheck", fname);
02189       rvalue = form.Compile();
02190    }
02191 
02192    return rvalue;
02193 }
02194 
02195 //______________________________________________________________________________
02196 void TFitEditor::DoAddition(Bool_t on)
02197 {
02198    // Slot connected to addition of predefined functions. It will
02199    // insert the next selected function with a plus sign so that it
02200    // doesn't override the current content of the formula.
02201 
02202    static Bool_t first = kFALSE;
02203    TString s = fEnteredFunc->GetText();
02204    if (on) {
02205       if (!first) {
02206          fSelLabel->SetText(s.Sizeof()>30?s(0,30)+"...":s);
02207          s += "(0)";
02208          fEnteredFunc->SetText(s.Data());
02209          first = kTRUE;
02210          ((TGCompositeFrame *)fSelLabel->GetParent())->Layout();
02211       }
02212    } else {
02213       first = kFALSE;
02214    }
02215 }
02216 
02217 //______________________________________________________________________________
02218 void TFitEditor::DoDataSet(Int_t selected)
02219 {
02220    // Selects the data set to be fitted
02221    if ( selected == kFP_NOSEL ) {
02222       DoNoSelection();
02223       return;
02224    }
02225 
02226    // Get the name and class of the selected object.
02227    TGTextLBEntry* textEntry = static_cast<TGTextLBEntry*>(fDataSet->GetListBox()->GetEntry(selected));
02228    TString textEntryStr = textEntry->GetText()->GetString();
02229    TString name = textEntry->GetText()->GetString()+textEntry->GetText()->First(':')+2;
02230    TString className = textEntryStr(0,textEntry->GetText()->First(':'));
02231    
02232    // Check the object exists in the ROOT session and it is registered
02233    TObject* objSelected(0);
02234    if ( className == "TTree" ) {
02235       // It's a tree, so the name is before the space (' ')
02236       TString lookStr;
02237       if ( name.First(' ') == kNPOS )
02238          lookStr = name;
02239       else 
02240          lookStr = name(0, name.First(' '));
02241       //cout << "\t1 SITREE: '" << lookStr << "'" << endl;
02242       objSelected = gROOT->FindObject(lookStr);
02243    } else {
02244       // It's not a tree, so the name is the complete string
02245       //cout << "\t1 NOTREE: '" << name << "'" << endl;
02246       objSelected = gROOT->FindObject(name);
02247    }
02248    if ( !objSelected ) 
02249    {
02250       //cerr << "Object not found! Please report the error! " << endl;
02251       return;
02252    }
02253 
02254    // If it is a tree, and there are no variables selected, show a dialog
02255    if ( objSelected->InheritsFrom(TTree::Class()) && 
02256         name.First(' ') == kNPOS ) {
02257       char variables[256] = {0}; char cuts[256] = {0};
02258       strlcpy(variables, "Sin input!", 256);
02259       new TTreeInput( fClient->GetRoot(), GetMainFrame(), variables, cuts );
02260       if ( strcmp ( variables, "" ) == 0 ) {
02261          DoNoSelection();
02262          return;
02263       }
02264       ProcessTreeInput(objSelected, selected, variables, cuts);
02265    }
02266 
02267    // Search the canvas where the object is drawn, if any
02268    TPad* currentPad = NULL;
02269    bool found = false;
02270    queue<TPad*> stPad;
02271    TIter padIter( gROOT->GetListOfCanvases() );
02272    while ( TObject* canvas = static_cast<TObject*>(padIter() ) ) {
02273       if ( dynamic_cast<TPad*>(canvas) )
02274          stPad.push(dynamic_cast<TPad*>(canvas));
02275    }
02276 
02277    while ( !stPad.empty() && !found ) {
02278       currentPad = stPad.front();
02279       stPad.pop();
02280       TIter elemIter( currentPad->GetListOfPrimitives() );
02281       while ( TObject* elem = static_cast<TObject*>(elemIter() ) ) {
02282          if ( elem == objSelected ) {
02283             found = true;
02284             break;
02285          } else if ( dynamic_cast<TPad*>(elem) )
02286             stPad.push( dynamic_cast<TPad*>(elem) );
02287       }
02288    }
02289 
02290    // Set the proper object and canvas (if found!)
02291    SetFitObject( found?currentPad:NULL, objSelected, kButton1Down);
02292 }
02293 
02294 void TFitEditor::ProcessTreeInput(TObject* objSelected, Int_t selected, TString variables, TString cuts)
02295 {
02296    // If the input is valid, insert the tree with the selections as an entry to fDataSet
02297    TString entryName = (objSelected)->ClassName(); entryName.Append("::"); entryName.Append((objSelected)->GetName());
02298    entryName.Append(" (\""); entryName.Append(variables); entryName.Append("\", \"");
02299    entryName.Append(cuts); entryName.Append("\")");
02300    Int_t newid = fDataSet->GetNumberOfEntries() + kFP_NOSEL;
02301    fDataSet->InsertEntry(entryName, newid, selected );
02302    fDataSet->Select(newid);
02303 }
02304 
02305 //______________________________________________________________________________
02306 void TFitEditor::DoFunction(Int_t selected)
02307 {
02308    // Slot connected to predefined fit function settings.
02309 
02310    TGTextLBEntry *te = (TGTextLBEntry *)fFuncList->GetSelectedEntry();
02311    bool editable = false;
02312    if (fNone->GetState() == kButtonDown || fNone->GetState() == kButtonDisabled) {
02313       // Get the function selected and check weather it is a raw C
02314       // function or not
02315       TF1* tmpTF1 = FindFunction();
02316       if ( !tmpTF1 ) {
02317          if (GetFitObjectListOfFunctions())
02318             tmpTF1 = (TF1*) GetFitObjectListOfFunctions()->FindObject( te->GetTitle() );
02319       }
02320       if ( tmpTF1 && strcmp(tmpTF1->GetExpFormula(), "") ) 
02321       {
02322          editable = kTRUE;
02323          fEnteredFunc->SetText(tmpTF1->GetExpFormula());
02324       }
02325       else
02326       {
02327          if ( selected <= kFP_USER )
02328             editable = kTRUE;
02329          else
02330             editable = kFALSE;
02331          fEnteredFunc->SetText(te->GetTitle());
02332       }
02333       // Once you have the function, set the editable.
02334       SetEditable(editable);
02335    } else if (fAdd->GetState() == kButtonDown) {
02336       // If the add button is down don't replace the fEnteredFunc text
02337       Int_t np = 0;
02338       TString s = "";
02339       if (!strcmp(fEnteredFunc->GetText(), "")) {
02340          fEnteredFunc->SetText(te->GetTitle());
02341       } else {
02342          s = fEnteredFunc->GetTitle();
02343          TFormula tmp("tmp", fEnteredFunc->GetText());
02344          np = tmp.GetNpar();
02345       }
02346       if (np)
02347          s += TString::Format("+%s(%d)", te->GetTitle(), np);
02348       else
02349          s += TString::Format("%s(%d)", te->GetTitle(), np);
02350       fEnteredFunc->SetText(s.Data());
02351       editable = true;
02352    }
02353 
02354    // Get the final name in fEnteredFunc to process the function that
02355    // it would create
02356    TString tmpStr = fEnteredFunc->GetText();
02357 
02358    // create TF1 with the passed string. Delete previous one if existing
02359    if (tmpStr.Contains("pol") || tmpStr.Contains("++")) {
02360       fLinearFit->SetState(kButtonDown, kTRUE);
02361    } else {
02362       fLinearFit->SetState(kButtonUp, kTRUE);
02363    }
02364 
02365    fEnteredFunc->SelectAll();
02366    fSelLabel->SetText(tmpStr.Sizeof()>30?tmpStr(0,30)+"...":tmpStr);
02367    ((TGCompositeFrame *)fSelLabel->GetParent())->Layout();
02368 
02369    // reset function parameters if the number of parameters of the new
02370    // function is different from the old one!
02371    TF1* fitFunc = GetFitFunction();
02372 
02373    if ( fitFunc && (unsigned int) fitFunc->GetNpar() != fFuncPars.size() )
02374       fFuncPars.clear();
02375    if ( fitFunc ) delete fitFunc;
02376 }
02377 
02378 //______________________________________________________________________________
02379 void TFitEditor::DoEnteredFunction()
02380 {
02381    // Slot connected to entered function in text entry.
02382 
02383    if (!strcmp(fEnteredFunc->GetText(), "")) return;
02384    
02385    // Check if the function is well built
02386    Int_t ok = CheckFunctionString(fEnteredFunc->GetText());
02387 
02388    if (ok != 0) {
02389       new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
02390                    "Error...", "DoEnteredFunction\nVerify the entered function string!",
02391                    kMBIconStop,kMBOk, 0);
02392       return;
02393    }
02394 
02395    // And set the label with the entered text if everything is fine.
02396    TString s = fEnteredFunc->GetText();
02397    fSelLabel->SetText(s.Sizeof()>30?s(0,30)+"...":s);
02398    ((TGCompositeFrame *)fSelLabel->GetParent())->Layout();
02399 }
02400 
02401 //______________________________________________________________________________
02402 void TFitEditor::DoLinearFit()
02403 {
02404    // Slot connected to linear fit settings.
02405 
02406    if (fLinearFit->GetState() == kButtonDown) {
02407       //fSetParam->SetState(kButtonDisabled);
02408       fBestErrors->SetState(kButtonDisabled);
02409       fImproveResults->SetState(kButtonDisabled);
02410       fRobustValue->SetState(kTRUE);
02411    } else {
02412       //fSetParam->SetState(kButtonUp);
02413       fBestErrors->SetState(kButtonUp);
02414       fImproveResults->SetState(kButtonUp);
02415       fRobustValue->SetState(kFALSE);
02416    }
02417 }
02418 
02419 //______________________________________________________________________________
02420 void TFitEditor::DoNoChi2()
02421 {
02422    // Slot connected to 'no chi2' option settings.
02423 
02424    if (fLinearFit->GetState() == kButtonUp)
02425       fLinearFit->SetState(kButtonDown, kTRUE);
02426 }
02427 
02428 //______________________________________________________________________________
02429 void TFitEditor::DoNoStoreDrawing()
02430 {
02431    // Slot connected to 'no storing, no drawing' settings.
02432    if (fNoDrawing->GetState() == kButtonUp)
02433       fNoDrawing->SetState(kButtonDown);
02434 }
02435 
02436 //______________________________________________________________________________
02437 void TFitEditor::DoPrintOpt(Bool_t on)
02438 {
02439    // Slot connected to print option settings.
02440 
02441    // Change the states of the buttons depending of which one is
02442    // selected.
02443    TGButton *btn = (TGButton *) gTQSender;
02444    Int_t id = btn->WidgetId();
02445    switch (id) {
02446       case kFP_PDEF:
02447          if (on) {
02448             fOptDefault->SetState(kButtonDown);
02449             fOptVerbose->SetState(kButtonUp);
02450             fOptQuiet->SetState(kButtonUp);
02451          }
02452          fStatusBar->SetText("Prn: DEF",4);
02453          break;
02454       case kFP_PVER:
02455          if (on) {
02456             fOptVerbose->SetState(kButtonDown);
02457             fOptDefault->SetState(kButtonUp);
02458             fOptQuiet->SetState(kButtonUp);
02459          }
02460          fStatusBar->SetText("Prn: VER",4);
02461          break;
02462       case kFP_PQET:
02463          if (on) {
02464             fOptQuiet->SetState(kButtonDown);
02465             fOptDefault->SetState(kButtonUp);
02466             fOptVerbose->SetState(kButtonUp);
02467          }
02468          fStatusBar->SetText("Prn: QT",4);
02469       default:
02470          break;
02471    }
02472 }
02473 
02474 //______________________________________________________________________________
02475 void TFitEditor::DoReset()
02476 {
02477    // Reset all fit parameters.
02478 
02479    if ( fParentPad ) {
02480       fParentPad->Modified();
02481       fParentPad->Update();
02482    }
02483    fEnteredFunc->SetText("gaus");
02484 
02485    // To restore temporary points and sliders
02486    UpdateGUI();
02487 
02488    if (fLinearFit->GetState() == kButtonDown)
02489       fLinearFit->SetState(kButtonUp, kTRUE);
02490    if (fBestErrors->GetState() == kButtonDown)
02491       fBestErrors->SetState(kButtonUp, kFALSE);
02492    if (fUseRange->GetState() == kButtonDown)
02493       fUseRange->SetState(kButtonUp, kFALSE);
02494    if (fAllWeights1->GetState() == kButtonDown)
02495       fAllWeights1->SetState(kButtonUp, kFALSE);
02496    if (fEmptyBinsWghts1->GetState() == kButtonDown)
02497       fEmptyBinsWghts1->SetState(kButtonUp, kFALSE);
02498    if (fImproveResults->GetState() == kButtonDown)
02499       fImproveResults->SetState(kButtonUp, kFALSE);
02500    if (fAdd2FuncList->GetState() == kButtonDown)
02501       fAdd2FuncList->SetState(kButtonUp, kFALSE);
02502    if (fUseGradient->GetState() == kButtonDown)
02503       fUseGradient->SetState(kButtonUp, kFALSE);
02504    if (fNoChi2->GetState() == kButtonDown)
02505       fNoChi2->SetState(kButtonUp, kFALSE);
02506    if (fDrawSame->GetState() == kButtonDown)
02507       fDrawSame->SetState(kButtonUp, kFALSE);
02508    if (fNoDrawing->GetState() == kButtonDown)
02509       fNoDrawing->SetState(kButtonUp, kFALSE);
02510    if (fNoStoreDrawing->GetState() == kButtonDown)
02511       fNoStoreDrawing->SetState(kButtonUp, kFALSE);
02512    fNone->SetState(kButtonDown, kTRUE);
02513    fFuncList->Select(1, kTRUE);
02514 
02515    // minimization tab
02516    if (fLibMinuit->GetState() != kButtonDown)
02517       fLibMinuit->SetState(kButtonDown, kTRUE);
02518    FillMinMethodList();
02519    if (fOptDefault->GetState() != kButtonDown)
02520       fOptDefault->SetState(kButtonDown, kTRUE);
02521    if (fErrorScale->GetNumber() != ROOT::Math::MinimizerOptions::DefaultErrorDef()) {
02522       fErrorScale->SetNumber(ROOT::Math::MinimizerOptions::DefaultErrorDef());
02523       fErrorScale->ReturnPressed();
02524    }   
02525    if (fTolerance->GetNumber() != ROOT::Math::MinimizerOptions::DefaultTolerance()) {
02526       fTolerance->SetNumber(ROOT::Math::MinimizerOptions::DefaultTolerance());
02527       fTolerance->ReturnPressed();
02528    }
02529    if (fIterations->GetNumber() != ROOT::Math::MinimizerOptions::DefaultMaxIterations()) {
02530       fIterations->SetIntNumber(ROOT::Math::MinimizerOptions::DefaultMaxIterations());
02531       fIterations->ReturnPressed();
02532    }
02533 }
02534 
02535 //______________________________________________________________________________
02536 void TFitEditor::DoSetParameters()
02537 {
02538    // Open set parameters dialog.
02539 
02540    // Get the function.
02541    TF1* fitFunc = GetFitFunction();
02542 
02543    if (!fitFunc) { Error("DoSetParameters","NUll function"); return; }
02544 
02545    // case of special functions (gaus, expo, etc...) if the function
02546    // has not defined the parameters yet. For those, don't let the
02547    // parameters to be all equal to 0, as we can provide some good
02548    // starting value.
02549    if (fFuncPars.size() == 0) { 
02550       switch (fType) {
02551       case kObjectHisto:
02552          InitParameters( fitFunc, (TH1*)fFitObject) ;
02553          break;
02554       case kObjectGraph:
02555          InitParameters( fitFunc, ((TGraph*)fFitObject));
02556          break;
02557       case kObjectMultiGraph:
02558          InitParameters( fitFunc, ((TMultiGraph*)fFitObject));
02559          break;
02560       case kObjectGraph2D:
02561          InitParameters( fitFunc, ((TGraph2D*)fFitObject));
02562          break;
02563       case kObjectHStack: 
02564       case kObjectTree:  
02565       default:
02566          break;
02567       }
02568       // The put these parameters into the fFuncPars structure
02569       GetParameters(fFuncPars, fitFunc);
02570    }                            
02571    else {
02572       // Otherwise, put the parameters in the function
02573       SetParameters(fFuncPars, fitFunc);
02574    }
02575 
02576    if ( fParentPad ) fParentPad->Disconnect("RangeAxisChanged()");
02577    Int_t ret = 0;
02578    new TFitParametersDialog(gClient->GetDefaultRoot(), GetMainFrame(), 
02579                             fitFunc, fParentPad, &ret);
02580    
02581    // Once the parameters are set in the fitfunction, save them.
02582    GetParameters(fFuncPars, fitFunc);
02583    
02584    if ( fParentPad ) fParentPad->Connect("RangeAxisChanged()", "TFitEditor", this, "UpdateGUI()");
02585 
02586    if ( fNone->GetState() != kButtonDisabled ) delete fitFunc;
02587 }
02588 
02589 //______________________________________________________________________________
02590 void TFitEditor::DoSliderXMoved()
02591 {
02592    // Slot connected to range settings on x-axis.
02593 
02594    if ( !fFitObject ) return;
02595    
02596    fSliderXMin->SetNumber( fXaxis->GetBinLowEdge( static_cast<Int_t>( fSliderX->GetMinPosition() ) ) );
02597    fSliderXMax->SetNumber( fXaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderX->GetMaxPosition() ) ) );
02598 
02599    fUseRange->SetState(kButtonUp);
02600 
02601    DrawSelection();
02602 }
02603 
02604 //______________________________________________________________________________
02605 void TFitEditor::DrawSelection(bool restore)
02606 {
02607    // Draws the square around the object showing where the limits for
02608    // fitting are.
02609 
02610    static Int_t  px1old, py1old, px2old, py2old; // to remember the square drawn.
02611 
02612    if ( !fParentPad ) return;
02613 
02614    if (restore) {
02615       px1old = fParentPad->XtoAbsPixel(fParentPad->GetUxmin());
02616       py1old = fParentPad->YtoAbsPixel(fParentPad->GetUymin());
02617       px2old = fParentPad->XtoAbsPixel(fParentPad->GetUxmax());
02618       py2old = fParentPad->YtoAbsPixel(fParentPad->GetUymax());
02619       return;
02620    }
02621 
02622    Int_t px1,py1,px2,py2;
02623 
02624    TVirtualPad *save = 0;
02625    save = gPad;
02626    gPad = fParentPad;
02627    gPad->cd();
02628 
02629    Double_t xleft = 0;
02630    Double_t xright = 0;
02631    xleft  = fXaxis->GetBinLowEdge((Int_t)((fSliderX->GetMinPosition())+0.5));
02632    xright = fXaxis->GetBinUpEdge((Int_t)((fSliderX->GetMaxPosition())+0.5));
02633 
02634    Float_t ymin, ymax;
02635    if ( fDim > 1 )
02636    {
02637       ymin = fYaxis->GetBinLowEdge((Int_t)((fSliderY->GetMinPosition())+0.5));//gPad->GetUymin();
02638       ymax = fYaxis->GetBinUpEdge((Int_t)((fSliderY->GetMaxPosition())+0.5));//gPad->GetUymax();
02639    }
02640    else 
02641    {
02642       ymin = gPad->GetUymin();
02643       ymax = gPad->GetUymax();
02644    }
02645 
02646    px1 = gPad->XtoAbsPixel(xleft);
02647    py1 = gPad->YtoAbsPixel(ymin);
02648    px2 = gPad->XtoAbsPixel(xright);
02649    py2 = gPad->YtoAbsPixel(ymax);
02650 
02651    gPad->GetCanvas()->FeedbackMode(kTRUE);
02652    gPad->SetLineWidth(1);
02653    gPad->SetLineColor(2);
02654    
02655    gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow);
02656    gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
02657 
02658    px1old = px1;
02659    py1old = py1;
02660    px2old = px2 ;
02661    py2old = py2;
02662 
02663    if(save) gPad = save;
02664 }
02665 
02666 //______________________________________________________________________________
02667 void TFitEditor::DoNumericSliderXChanged()
02668 {
02669    // Sincronize the numeric sliders with the graphical one.
02670    if ( fSliderXMin->GetNumber() > fSliderXMax->GetNumber() ) {
02671       float xmin, xmax;
02672       fSliderX->GetPosition(xmin, xmax);
02673       fSliderXMin->SetNumber( fXaxis->GetBinLowEdge( static_cast<Int_t>( xmin ) ) );
02674       fSliderXMax->SetNumber( fXaxis->GetBinUpEdge ( static_cast<Int_t>( xmax ) ) );
02675       return;
02676    }
02677 
02678    fSliderX->SetPosition(fXaxis->FindBin( fSliderXMin->GetNumber() ),
02679                          fXaxis->FindBin( fSliderXMax->GetNumber() ));
02680 
02681    fUseRange->SetState(kButtonUp);
02682 
02683    DrawSelection();
02684 }
02685 
02686 //______________________________________________________________________________
02687 void TFitEditor::DoSliderYMoved()
02688 {
02689    // Slot connected to range settings on y-axis.
02690 
02691    if ( !fFitObject ) return;
02692 
02693    fSliderYMin->SetNumber( fYaxis->GetBinLowEdge( static_cast<Int_t>( fSliderY->GetMinPosition() ) ) );
02694    fSliderYMax->SetNumber( fYaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderY->GetMaxPosition() ) ) );
02695    
02696    fUseRange->SetState(kButtonUp);
02697 
02698    DrawSelection();
02699 }
02700 
02701 //______________________________________________________________________________
02702 void TFitEditor::DoNumericSliderYChanged()
02703 {
02704    //syncronize the numeric slider with the graphical one.
02705    if ( fSliderYMin->GetNumber() > fSliderYMax->GetNumber() ) {
02706       float ymin, ymax;
02707       fSliderY->GetPosition(ymin, ymax);
02708       fSliderYMin->SetNumber( fYaxis->GetBinLowEdge( static_cast<Int_t>( ymin ) ) );
02709       fSliderYMax->SetNumber( fYaxis->GetBinUpEdge ( static_cast<Int_t>( ymax ) ) );
02710       return;
02711    }
02712 
02713    fSliderY->SetPosition( fYaxis->FindBin( fSliderYMin->GetNumber() ),
02714                           fYaxis->FindBin( fSliderYMax->GetNumber() ));
02715 
02716    fUseRange->SetState(kButtonUp);
02717 
02718    DrawSelection();
02719 }
02720 
02721 //______________________________________________________________________________
02722 void TFitEditor::DoSliderZMoved()
02723 {
02724    // Slot connected to range settings on z-axis.
02725 
02726 }
02727 
02728 //______________________________________________________________________________
02729 void TFitEditor::DoUserDialog()
02730 {
02731    // Open a dialog for getting a user defined method.
02732 
02733    new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
02734                 "Info", "Dialog of user method is not implemented yet",
02735                 kMBIconAsterisk,kMBOk, 0);
02736 }
02737 
02738 //______________________________________________________________________________
02739 void TFitEditor::SetFunction(const char *function)
02740 {
02741    // Set the function to be used in performed fit.
02742 
02743    fEnteredFunc->SetText(function);
02744 }
02745 
02746 //______________________________________________________________________________
02747 Bool_t TFitEditor::SetObjectType(TObject* obj)
02748 {
02749    // Check whether the object suitable for fitting and set 
02750    // its type, dimension and method combo box accordingly.
02751    
02752    Bool_t set = kFALSE;
02753 
02754    // For each kind of object, set a different status in the fit
02755    // panel.
02756    if (obj->InheritsFrom(TGraph::Class())) {
02757       fType = kObjectGraph;
02758       set = kTRUE;
02759       fDim = 1;
02760       fMethodList->RemoveAll();
02761       fMethodList->AddEntry("Chi-square", kFP_MCHIS);
02762       fMethodList->Select(kFP_MCHIS, kFALSE);
02763       fRobustValue->SetState(kTRUE);
02764       fRobustValue->GetNumberEntry()->SetToolTipText("Set robust value");
02765    } else if (obj->InheritsFrom(TGraph2D::Class())) {
02766       fType = kObjectGraph2D;
02767       set = kTRUE;
02768       fDim = 2;
02769       fMethodList->RemoveAll();
02770       fMethodList->AddEntry("Chi-square", kFP_MCHIS);
02771       fMethodList->Select(kFP_MCHIS, kFALSE);
02772    } else if (obj->InheritsFrom(THStack::Class())) {
02773       fType = kObjectHStack;
02774       set = kTRUE;
02775       TH1 *hist = (TH1 *)((THStack *)obj)->GetHists()->First();
02776       fDim = hist->GetDimension();
02777       fMethodList->RemoveAll();
02778       fMethodList->AddEntry("Chi-square", kFP_MCHIS);
02779       fMethodList->Select(kFP_MCHIS, kFALSE);
02780    } else if (obj->InheritsFrom(TTree::Class())) {
02781       fType = kObjectTree;
02782       set = kTRUE;
02783       TString variables, cuts;
02784       GetTreeVarsAndCuts(fDataSet, variables, cuts);
02785       fDim = 1;
02786       for ( int i = 0; i < variables.Length() && fDim <= 2; ++i )
02787          if ( ':' == variables[i] ) fDim += 1;
02788       // For any three  of dimension bigger than 2,  set the dimension
02789       // to 0,  as we cannot infer  the dimension from  the TF1s, it's
02790       // better to have 0 as reference.
02791       if ( fDim > 2 ) fDim = 0;
02792       fMethodList->RemoveAll();
02793       fMethodList->AddEntry("Unbinned Likelihood", kFP_MUBIN);
02794       fMethodList->Select(kFP_MUBIN, kFALSE);      
02795    } else if (obj->InheritsFrom(TH1::Class())){
02796       fType = kObjectHisto;
02797       set = kTRUE;
02798       fDim = ((TH1*)obj)->GetDimension();
02799       fMethodList->RemoveAll();
02800       fMethodList->AddEntry("Chi-square", kFP_MCHIS);
02801       fMethodList->AddEntry("Binned Likelihood", kFP_MBINL);
02802       fMethodList->Select(kFP_MCHIS, kFALSE);
02803    } else if (obj->InheritsFrom(TMultiGraph::Class())) {
02804       fType = kObjectMultiGraph;
02805       set = kTRUE;
02806       fDim = 1;
02807       fMethodList->RemoveAll();
02808       fMethodList->AddEntry("Chi-square", kFP_MCHIS);
02809       fMethodList->Select(kFP_MCHIS, kFALSE);
02810       fRobustValue->SetState(kTRUE);
02811       fRobustValue->GetNumberEntry()->SetToolTipText("Set robust value");
02812    }
02813 
02814    // Depending on the dimension of the object, allow the
02815    // visualization of sliders.
02816    if ( fDim < 2 || fType == kObjectTree )
02817       fGeneral->HideFrame(fSliderYParent);
02818    else
02819       fGeneral->ShowFrame(fSliderYParent);
02820 
02821    if ( fDim < 1 || fType == kObjectTree )
02822       fGeneral->HideFrame(fSliderXParent);
02823    else
02824       fGeneral->ShowFrame(fSliderXParent);
02825 
02826    // And also, depending on the dimension, add predefined functions.
02827    if ( fDim == 1 ) {
02828       if ( !fTypeFit->FindEntry("Predef-1D") ) 
02829          fTypeFit->InsertEntry("Predef-1D", kFP_PRED1D, kFP_PREVFIT);
02830    } else {
02831       if ( fTypeFit->FindEntry("Predef-1D") )
02832          fTypeFit->RemoveEntry(kFP_PRED1D);
02833    }
02834 
02835    if ( fDim == 2 ) {
02836       if ( !fTypeFit->FindEntry("Predef-2D") ) 
02837          fTypeFit->InsertEntry("Predef-2D", kFP_PRED2D, kFP_PREVFIT);
02838    } else {
02839       if ( fTypeFit->FindEntry("Predef-2D") )
02840          fTypeFit->RemoveEntry(kFP_PRED2D);
02841    }
02842 
02843    return set;
02844 }
02845 
02846 //______________________________________________________________________________
02847 void TFitEditor::ShowObjectName(TObject* obj)
02848 {
02849    // Show object name on the top.
02850 
02851    TString name;
02852    bool isTree = false;
02853    
02854    // Build the string to be compared to look for the object.
02855    if (obj) {
02856       name = obj->ClassName();
02857       name.Append("::");
02858       name.Append(obj->GetName());
02859       isTree = strcmp(obj->ClassName(), "TTree") == 0;
02860    } else {
02861       name = "No object selected";
02862    }
02863    fStatusBar->SetText(name.Data(),0);
02864 
02865    // If the selection was done in the fDataSet combo box, there is no need
02866    // to search through the list
02867    TGTextLBEntry* selectedEntry = static_cast<TGTextLBEntry*> ( fDataSet->GetSelectedEntry());
02868    if ( selectedEntry ) {
02869       TString selectedName = selectedEntry->GetText()->GetString();
02870       if ( isTree )
02871          selectedName = selectedName(0, selectedName.First(' '));
02872       if ( name.CompareTo(selectedName) == 0 ) {
02873          Layout();
02874          return;
02875       }
02876    }
02877 
02878    // Search through the list for the object
02879    Int_t entryId = kFP_NOSEL+1;
02880    bool found = false;
02881    while ( TGTextLBEntry* entry = static_cast<TGTextLBEntry*> 
02882            ( fDataSet->GetListBox()->GetEntry(entryId)) ) {
02883       TString compareName = entry->GetText()->GetString();
02884       if ( isTree ) 
02885          compareName = compareName(0, compareName.First(' '));
02886       if ( name.CompareTo(compareName) == 0 ) {
02887          // If the object is found, select it
02888          fDataSet->Select(entryId, false);
02889          found = true;
02890          break;
02891       }
02892       entryId += 1;
02893    }
02894 
02895    // If the object was not found, add it and select it.
02896    if ( !found ) {
02897       fDataSet->AddEntry(name.Data(), entryId);
02898       fDataSet->Select(entryId, kTRUE);
02899    }
02900    
02901    Layout();
02902 }
02903 
02904 //______________________________________________________________________________
02905 Option_t *TFitEditor::GetDrawOption() const
02906 {
02907    // Get draw options of the selected object.
02908 
02909    if (!fParentPad) return "";
02910 
02911    TListIter next(fParentPad->GetListOfPrimitives());
02912    TObject *obj;
02913    while ((obj = next())) {
02914       if (obj == fFitObject) return next.GetOption();
02915    }
02916    return "";
02917 }
02918 
02919 //______________________________________________________________________________
02920 void TFitEditor::DoLibrary(Bool_t on)
02921 {
02922    // Set selected minimization library in use.
02923 
02924    TGButton *bt = (TGButton *)gTQSender;
02925    Int_t id = bt->WidgetId(); 
02926 
02927    switch (id) {
02928 
02929       // Depending on the selected library, set the state of the rest
02930       // of the buttons.
02931       case kFP_LMIN:
02932          {
02933             if (on) {
02934                fLibMinuit->SetState(kButtonDown);
02935                fLibMinuit2->SetState(kButtonUp);
02936                fLibFumili->SetState(kButtonUp);
02937                if ( fLibGSL->GetState() != kButtonDisabled )
02938                   fLibGSL->SetState(kButtonUp);
02939                if ( fLibGenetics->GetState() != kButtonDisabled )
02940                fLibGenetics->SetState(kButtonUp);
02941                fStatusBar->SetText("LIB Minuit", 1);
02942             }
02943             
02944          }
02945          break;
02946       
02947       case kFP_LMIN2:
02948          {
02949             if (on) {
02950                fLibMinuit->SetState(kButtonUp);
02951                fLibMinuit2->SetState(kButtonDown);
02952                fLibFumili->SetState(kButtonUp);
02953                if ( fLibGSL->GetState() != kButtonDisabled )
02954                   fLibGSL->SetState(kButtonUp);
02955                if ( fLibGenetics->GetState() != kButtonDisabled )
02956                   fLibGenetics->SetState(kButtonUp);
02957                fStatusBar->SetText("LIB Minuit2", 1);
02958             }
02959          }
02960          break;
02961       
02962       case kFP_LFUM:
02963          {
02964             if (on) {
02965                fLibMinuit->SetState(kButtonUp);
02966                fLibMinuit2->SetState(kButtonUp);
02967                fLibFumili->SetState(kButtonDown);
02968                if ( fLibGSL->GetState() != kButtonDisabled )
02969                   fLibGSL->SetState(kButtonUp);
02970                if ( fLibGenetics->GetState() != kButtonDisabled )
02971                   fLibGenetics->SetState(kButtonUp);
02972                fStatusBar->SetText("LIB Fumili", 1);
02973             }
02974          }
02975          break;
02976       case kFP_LGSL:
02977          {
02978             if (on) {
02979                fLibMinuit->SetState(kButtonUp);
02980                fLibMinuit2->SetState(kButtonUp);
02981                fLibFumili->SetState(kButtonUp);
02982                if ( fLibGSL->GetState() != kButtonDisabled )
02983                   fLibGSL->SetState(kButtonDown);
02984                if ( fLibGenetics->GetState() != kButtonDisabled )
02985                   fLibGenetics->SetState(kButtonUp);
02986                fStatusBar->SetText("LIB GSL", 1);
02987             }
02988          }
02989          break;
02990       case kFP_LGAS:
02991       {
02992          if (on) {
02993             fLibMinuit->SetState(kButtonUp);
02994             fLibMinuit2->SetState(kButtonUp);
02995             fLibFumili->SetState(kButtonUp);
02996             if ( fLibGSL->GetState() != kButtonDisabled )
02997                fLibGSL->SetState(kButtonUp);
02998             if ( fLibGenetics->GetState() != kButtonDisabled )
02999                fLibGenetics->SetState(kButtonDown);
03000             fStatusBar->SetText("LIB Genetics", 1);
03001          }
03002       }
03003       default:
03004          break;
03005    }
03006    FillMinMethodList();
03007 }
03008 
03009 //______________________________________________________________________________
03010 void TFitEditor::DoMinMethod(Int_t )
03011 {
03012    // Set selected minimization method in use.
03013 
03014    if ( fMinMethodList->GetSelected() == kFP_MIGRAD )
03015       fStatusBar->SetText("MIGRAD",2);
03016    else if ( fMinMethodList->GetSelected() == kFP_FUMILI)
03017       fStatusBar->SetText("FUMILI",2);
03018    else if ( fMinMethodList->GetSelected() == kFP_SIMPLX )
03019       fStatusBar->SetText("SIMPLEX",2);
03020    else if ( fMinMethodList->GetSelected() == kFP_SCAN )
03021       fStatusBar->SetText("SCAN",2);
03022    else if ( fMinMethodList->GetSelected() == kFP_COMBINATION )
03023       fStatusBar->SetText("Combination",2);
03024    else if ( fMinMethodList->GetSelected() == kFP_GSLFR )
03025       fStatusBar->SetText("CONJFR",2);
03026    else if ( fMinMethodList->GetSelected() == kFP_GSLPR )
03027       fStatusBar->SetText("CONJPR",2);
03028    else if ( fMinMethodList->GetSelected() == kFP_BFGS )
03029       fStatusBar->SetText("BFGS",2);
03030    else if ( fMinMethodList->GetSelected() == kFP_BFGS2 )
03031       fStatusBar->SetText("BFGS2",2);
03032    else if ( fMinMethodList->GetSelected() == kFP_GSLLM )
03033       fStatusBar->SetText("GSLLM",2);
03034    else if ( fMinMethodList->GetSelected() == kFP_GSLSA)
03035       fStatusBar->SetText("SimAn",2);
03036    else if ( fMinMethodList->GetSelected() == kFP_TMVAGA )
03037       fStatusBar->SetText("TMVAGA",2);
03038    else if ( fMinMethodList->GetSelected() == kFP_GALIB )
03039       fStatusBar->SetText("GALIB",2);
03040 
03041 
03042 }
03043 
03044 //______________________________________________________________________________
03045 void TFitEditor::DoMaxIterations()
03046 {
03047    // Set the maximum number of iterations.
03048 
03049    Long_t itr = fIterations->GetIntNumber();
03050    fStatusBar->SetText(Form("Itr: %ld",itr),2);
03051 }
03052 
03053 //______________________________________________________________________________
03054 void TFitEditor::MakeTitle(TGCompositeFrame *parent, const char *title)
03055 {
03056    // Create section title in the GUI.
03057 
03058    TGCompositeFrame *ht = new TGCompositeFrame(parent, 350, 10, 
03059                                                kFixedWidth | kHorizontalFrame);
03060    ht->AddFrame(new TGLabel(ht, title),
03061                 new TGLayoutHints(kLHintsLeft, 1, 1, 0, 0));
03062    ht->AddFrame(new TGHorizontal3DLine(ht),
03063                 new TGLayoutHints(kLHintsExpandX | kLHintsCenterY, 5, 5, 2, 2));
03064    parent->AddFrame(ht, new TGLayoutHints(kLHintsTop, 5, 0, 5, 0));
03065 }
03066 
03067 //______________________________________________________________________________
03068 TF1* TFitEditor::HasFitFunction()
03069 {
03070    // Look in the list of function for TF1. If a TF1 is
03071    // found in the list of functions, it will be returned
03072    
03073    // Get the list of functions of the fit object
03074    TList *lf = GetFitObjectListOfFunctions();
03075 
03076    // If it exists
03077    if ( lf ) {
03078       // Add the posibility to select previous fit function
03079       if ( !fTypeFit->FindEntry("Prev. Fit") )
03080          fTypeFit->InsertEntry("Prev. Fit",kFP_PREVFIT, kFP_UFUNC);
03081 
03082       // Then add all these functions to the fPrefFit structure.
03083       TObject *obj2;
03084       TIter next(lf, kIterBackward);
03085       // Go over all the elements in lf
03086       while ((obj2 = next())) {
03087          if (obj2->InheritsFrom(TF1::Class())) {
03088             TF1* func = (TF1 *)obj2;
03089             fPrevFitIter it;
03090             // No go over all elements in fPrevFit
03091             for ( it = fPrevFit.begin(); it != fPrevFit.end(); ++it) {
03092                // To see wheather the object corresponds with fFitObject
03093                if ( it->first != fFitObject ) continue;
03094                // And if so, whether the function is already included
03095                if ( strcmp( func->GetName(), it->second->GetName() ) == 0 )
03096                   break;
03097                if ( strcmp( func->GetName(), "PrevFitTMP" ) == 0 )
03098                   break;
03099             }
03100             // Only if the function is not already in fPrevFit, the
03101             // breaks in the loops would make it to be different to
03102             // fPrevFit.end() if the function is already stored
03103             if ( it == fPrevFit.end() ) {
03104                fPrevFit.insert( FitFuncMap_t::value_type( fFitObject, static_cast<TF1*>( copyTF1( func ) ) ) );
03105             }
03106          }
03107       }
03108 
03109       // Select the PrevFit set
03110       fTypeFit->Select(kFP_PREVFIT);
03111       // And fill the function list
03112       FillFunctionList();
03113       fDrawAdvanced->SetState(kButtonUp);
03114 
03115    } else {
03116       // If there is no prev fit functions.
03117       fTypeFit->Select(kFP_UFUNC);
03118       // Call FillFunctionList as it might happen that the user is
03119       // changing from a TTree to another one, and thus the fFuncList
03120       // if not properly filled
03121       FillFunctionList();
03122    }
03123 
03124    fDrawAdvanced->SetState(kButtonDisabled);
03125    return 0;
03126 }
03127 
03128 //______________________________________________________________________________
03129 void TFitEditor::RetrieveOptions(Foption_t& fitOpts, TString& drawOpts, ROOT::Math::MinimizerOptions& minOpts, Int_t npar)
03130 {
03131    // Retrieve the fitting options from all the widgets.
03132 
03133    drawOpts = "";
03134 
03135    fitOpts.Range    = (fUseRange->GetState() == kButtonDown);
03136    fitOpts.Integral = (fIntegral->GetState() == kButtonDown);
03137    fitOpts.More     = (fImproveResults->GetState() == kButtonDown);
03138    fitOpts.Errors   = (fBestErrors->GetState() == kButtonDown);
03139    fitOpts.Like = (fMethodList->GetSelected() != kFP_MCHIS);
03140 
03141    if (fEmptyBinsWghts1->GetState() == kButtonDown)
03142       fitOpts.W1 = 2;
03143    else if (fAllWeights1->GetState() == kButtonDown)
03144       fitOpts.W1 = 1;
03145 
03146    TString tmpStr = fEnteredFunc->GetText();
03147    if ( !(fLinearFit->GetState() == kButtonDown) &&
03148         (tmpStr.Contains("pol") || tmpStr.Contains("++")) )
03149       fitOpts.Minuit = 1;
03150 
03151    if ( (int) fFuncPars.size() == npar )
03152       for ( Int_t i = 0; i < npar; ++i )
03153          if ( fFuncPars[i][PAR_MIN] != fFuncPars[i][PAR_MAX] )
03154          {
03155             fitOpts.Bound = 1;
03156             break;
03157          }
03158    
03159    fitOpts.Nochisq  = (fNoChi2->GetState() == kButtonDown);
03160    fitOpts.Nostore  = (fNoStoreDrawing->GetState() == kButtonDown);
03161    fitOpts.Nograph  = (fNoDrawing->GetState() == kButtonDown);
03162    fitOpts.Plus     = (fAdd2FuncList->GetState() == kButtonDown);
03163    fitOpts.Gradient = (fUseGradient->GetState() == kButtonDown);
03164    fitOpts.Quiet    = ( fOptQuiet->GetState() == kButtonDown );
03165    fitOpts.Verbose  = ( fOptVerbose->GetState() == kButtonDown );
03166 
03167    if ( !(fType != kObjectGraph) && (fLinearFit->GetState() == kButtonDown) )
03168    {
03169       fitOpts.Robust = 1;
03170       fitOpts.hRobust = fRobustValue->GetNumber();
03171    }
03172 
03173    drawOpts = GetDrawOption();
03174 
03175    if ( fLibMinuit->GetState() == kButtonDown )
03176       minOpts.SetMinimizerType ( "Minuit");
03177    else if ( fLibMinuit2->GetState() == kButtonDown)
03178       minOpts.SetMinimizerType ( "Minuit2" );
03179    else if ( fLibFumili->GetState() == kButtonDown )
03180       minOpts.SetMinimizerType ("Fumili" );
03181    else if ( fLibGSL->GetState() == kButtonDown )
03182       minOpts.SetMinimizerType ("GSLMultiMin" );
03183 
03184    if ( fMinMethodList->GetSelected() == kFP_MIGRAD )
03185       minOpts.SetMinimizerAlgorithm( "Migrad" );
03186    else if ( fMinMethodList->GetSelected() == kFP_FUMILI)
03187       if ( fLibMinuit2->GetState() == kButtonDown )
03188          minOpts.SetMinimizerAlgorithm( "Fumili2" );
03189       else 
03190          minOpts.SetMinimizerAlgorithm( "Fumili" );
03191    else if ( fMinMethodList->GetSelected() == kFP_SIMPLX )
03192       minOpts.SetMinimizerAlgorithm( "Simplex" );
03193    else if ( fMinMethodList->GetSelected() == kFP_SCAN )
03194       minOpts.SetMinimizerAlgorithm( "Scan" );
03195    else if ( fMinMethodList->GetSelected() == kFP_COMBINATION )
03196       minOpts.SetMinimizerAlgorithm( "Minimize" );
03197    else if ( fMinMethodList->GetSelected() == kFP_GSLFR )
03198       minOpts.SetMinimizerAlgorithm( "conjugatefr" );
03199    else if ( fMinMethodList->GetSelected() == kFP_GSLPR )
03200       minOpts.SetMinimizerAlgorithm( "conjugatepr" );
03201    else if ( fMinMethodList->GetSelected() == kFP_BFGS )
03202       minOpts.SetMinimizerAlgorithm( "bfgs" );
03203    else if ( fMinMethodList->GetSelected() == kFP_BFGS2 )
03204       minOpts.SetMinimizerAlgorithm( "bfgs2" );
03205    else if ( fMinMethodList->GetSelected() == kFP_GSLLM ) {
03206       minOpts.SetMinimizerType ("GSLMultiFit" );
03207       minOpts.SetMinimizerAlgorithm( "" );
03208    } else if ( fMinMethodList->GetSelected() == kFP_GSLSA) {
03209       minOpts.SetMinimizerType ("GSLSimAn" );
03210       minOpts.SetMinimizerAlgorithm( "" );
03211    } else if ( fMinMethodList->GetSelected() == kFP_TMVAGA) {
03212       minOpts.SetMinimizerType ("Geneti2c" );
03213       minOpts.SetMinimizerAlgorithm( "" );
03214    } else if ( fMinMethodList->GetSelected() == kFP_GALIB) {
03215       minOpts.SetMinimizerType ("GAlibMin" );
03216       minOpts.SetMinimizerAlgorithm( "" );
03217    }
03218 
03219    minOpts.SetErrorDef ( fErrorScale->GetNumber() );
03220    minOpts.SetTolerance( fTolerance->GetNumber() );
03221    minOpts.SetMaxIterations(fIterations->GetIntNumber());
03222    minOpts.SetMaxFunctionCalls(fIterations->GetIntNumber());
03223 }
03224 
03225 void TFitEditor::SetEditable(Bool_t state)
03226 {
03227    // Set the state of some input widgets depending on whether the fit
03228    // function can be defined by text or if it is an existing one.
03229    if ( state )
03230    {
03231       fEnteredFunc->SetState(kTRUE);
03232       fAdd->SetState(kButtonUp, kFALSE);
03233       // fNone::State is the one used as reference
03234       fNone->SetState(kButtonDown, kFALSE);
03235    } else {
03236       fEnteredFunc->SetState(kFALSE);
03237       fAdd->SetState(kButtonDisabled, kFALSE);
03238       fNone->SetState(kButtonDisabled, kFALSE);
03239    }
03240 }
03241 
03242 void TFitEditor::GetRanges(ROOT::Fit::DataRange& drange)
03243 {
03244    // Return the ranges selected by the sliders.
03245    
03246    // It's not working for trees as they don't have TAxis.
03247    if ( fType == kObjectTree ) return;
03248 
03249    if ( fType != kObjectTree ) {
03250       Int_t ixmin = (Int_t)(fSliderX->GetMinPosition()); 
03251       Int_t ixmax = (Int_t)(fSliderX->GetMaxPosition()); 
03252       Double_t xmin = fXaxis->GetBinLowEdge(ixmin);
03253       Double_t xmax = fXaxis->GetBinUpEdge(ixmax);
03254       drange.AddRange(0,xmin, xmax);
03255    }
03256 
03257    if ( fDim > 1 ) {
03258       assert(fYaxis); 
03259       Int_t iymin = (Int_t)(fSliderY->GetMinPosition()); 
03260       Int_t iymax = (Int_t)(fSliderY->GetMaxPosition()); 
03261       Double_t ymin = fYaxis->GetBinLowEdge(iymin);
03262       Double_t ymax = fYaxis->GetBinUpEdge(iymax);
03263       drange.AddRange(1,ymin, ymax);
03264    }
03265    if ( fDim > 2 ) {
03266       assert(fZaxis); 
03267       Int_t izmin = (Int_t)(fSliderZ->GetMinPosition()); 
03268       Int_t izmax = (Int_t)(fSliderZ->GetMaxPosition()); 
03269       Double_t zmin = fZaxis->GetBinLowEdge(izmin);
03270       Double_t zmax = fZaxis->GetBinUpEdge(izmax);
03271       drange.AddRange(2,zmin, zmax);
03272    }
03273 }
03274 
03275 TList* TFitEditor::GetFitObjectListOfFunctions()
03276 {
03277    // Get the list of functions previously used in the fitobject.
03278 
03279    TList *listOfFunctions = 0;
03280    if ( fFitObject ) {
03281       switch (fType) {
03282             
03283       case kObjectHisto:
03284          listOfFunctions = ((TH1 *)fFitObject)->GetListOfFunctions();
03285          break;
03286             
03287       case kObjectGraph:
03288          listOfFunctions = ((TGraph *)fFitObject)->GetListOfFunctions();
03289          break;
03290             
03291       case kObjectMultiGraph:
03292          listOfFunctions = ((TMultiGraph *)fFitObject)->GetListOfFunctions();
03293          break;
03294          
03295       case kObjectGraph2D:
03296          listOfFunctions = ((TGraph2D *)fFitObject)->GetListOfFunctions();
03297          break;
03298          
03299       case kObjectHStack:
03300       case kObjectTree: 
03301       default:
03302          break;
03303       }
03304    }
03305    return listOfFunctions;
03306 }
03307 
03308 void TFitEditor::GetFunctionsFromSystem()
03309 {
03310    // Looks for all the functions registered in the current ROOT
03311    // session.
03312 
03313    // First, clean the copies stored in fSystemFunc
03314    for ( fSystemFuncIter it = fSystemFuncs.begin();
03315          it != fSystemFuncs.end();
03316          ++it ) {
03317       delete (*it);
03318    }
03319 
03320    fSystemFuncs.clear();
03321 
03322    // Be carefull not to store functions that will be in the
03323    // predefined section
03324    const unsigned int nfuncs = 16;
03325    const char* fnames[nfuncs] = { "gaus" ,   "gausn", "expo", "landau",
03326                                   "landaun", "pol0",  "pol1", "pol2",
03327                                   "pol3",    "pol4",  "pol5", "pol6",
03328                                   "pol7",    "pol8",  "pol9", "user"
03329    };
03330 
03331    // No go through all the objects registered in gROOT
03332    TIter functionsIter(gROOT->GetListOfFunctions());
03333    TObject* obj;
03334    while( ( obj = (TObject*) functionsIter() ) ) {
03335       // And if they are TF1s
03336       if ( TF1* func = dynamic_cast<TF1*>(obj) ) {
03337          bool addFunction = true;
03338          // And they are not already registered in fSystemFunc
03339          for ( unsigned int i = 0; i < nfuncs; ++i ) {
03340             if ( strcmp( func->GetName(), fnames[i] ) == 0 ) {
03341                addFunction = false;
03342                break;
03343             }
03344          }
03345          // Add them.
03346          if ( addFunction )
03347             fSystemFuncs.push_back( copyTF1(func) ); 
03348       }
03349    }
03350 }
03351 
03352 TList* TFitEditor::GetListOfFittingFunctions(TObject* obj)
03353 {
03354    // This function returns a TList with all the functions used in the
03355    // FitPanel to fit a given object. If the object passed is NULL,
03356    // then the object used is the currently selected one. It is
03357    // important to notice that the FitPanel is still the owner of
03358    // those functions. This means that the user SHOULD NOT delete any
03359    // of these functions, as the FitPanel will do so in the
03360    // destructor.
03361 
03362    if (!obj) obj = fFitObject;
03363 
03364    TList *retList = new TList();
03365 
03366    pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(obj);
03367    for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
03368       retList->Add(it->second);
03369    }
03370 
03371    return retList;
03372 }
03373 
03374 TF1* TFitEditor::GetFitFunction() 
03375 {
03376    // Get the fit function selected or declared in the fiteditor
03377 
03378    TF1 *fitFunc = 0;
03379    // If the function is not editable ==> it means it is registered in
03380    // gROOT
03381    if ( fNone->GetState() == kButtonDisabled )
03382    {
03383       // So we find it
03384       TF1* tmpF1 = FindFunction();
03385       // And if we don't find it, then it means there is something wrong!
03386       if ( tmpF1 == 0 )
03387       {
03388                new TGMsgBox(fClient->GetRoot(), GetMainFrame(),
03389                             "Error...", "GetFitFunction\nVerify the entered function string!",
03390                             kMBIconStop,kMBOk, 0);
03391                return 0;
03392       }
03393 
03394       // Now we make a copy that will be used temporary. The caller of
03395       // the function should delete the returned function.
03396       fitFunc = (TF1*)tmpF1->IsA()->New();
03397       tmpF1->Copy(*fitFunc);
03398       // Copy the parameters of the function, if and only if the
03399       // parameters stored does not correspond with the ones of these
03400       // functions. Perhaps the user has already called
03401       // DoSetParameters. There is no way to know whether the
03402       // parameters have been modified, so we check the size of
03403       // fFuncPars against number of parameters.
03404       if ( int(fFuncPars.size()) != tmpF1->GetNpar() )
03405       {
03406          fitFunc->SetParameters(tmpF1->GetParameters());
03407          GetParameters(fFuncPars, fitFunc);
03408       } else {
03409          SetParameters(fFuncPars, fitFunc);
03410       }
03411    }
03412 
03413    // If, we have no function at this point, it means that is is
03414    // described in fEnteredFunc, so we create it from scratch.
03415    if ( fitFunc == 0 )
03416    {
03417       ROOT::Fit::DataRange drange; 
03418       GetRanges(drange);
03419       double xmin, xmax, ymin, ymax, zmin, zmax;
03420       drange.GetRange(xmin, xmax, ymin, ymax, zmin, zmax);
03421 
03422       // Depending of course on the number of dimensions the object
03423       // has. These commands will raise an error message if the user
03424       // has not defined the function properly
03425       if ( fDim == 1 || fDim == 0 ) {
03426          fitFunc = new TF1("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax );
03427       }
03428       else if ( fDim == 2 ) {
03429          fitFunc = new TF2("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax, ymin, ymax );
03430       }
03431       else if ( fDim == 3 ) {
03432          fitFunc = new TF3("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax, ymin, ymax, zmin, zmax );
03433       }
03434 
03435       // if the function is not a C defined
03436       if ( fNone->GetState() != kButtonDisabled )
03437       {
03438          // and the formulas are the same
03439          TF1* tmpF1 = FindFunction();
03440          if ( tmpF1 != 0 && fitFunc != 0 && 
03441               strcmp(tmpF1->GetExpFormula(), fEnteredFunc->GetText()) == 0 ) {
03442             // copy the parameters!
03443             if ( int(fFuncPars.size()) != tmpF1->GetNpar() )
03444             {
03445                fitFunc->SetParameters(tmpF1->GetParameters());
03446                GetParameters(fFuncPars, fitFunc);
03447             } else 
03448                SetParameters(fFuncPars, fitFunc);
03449          }
03450       }
03451    }
03452 
03453    return fitFunc;
03454 }

Generated on Tue Jul 5 14:19:23 2011 for ROOT_528-00b_version by  doxygen 1.5.1