Logo ROOT  
Reference Guide
TFitEditor.cxx
Go to the documentation of this file.
1// @(#)root/fitpanel:$Id: ed8d59036b6a51c67cd739c2c75aa7780b847bf8 $
2// Author: Ilka Antcheva, Lorenzo Moneta 10/08/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12
13/** \class TFitEditor
14 \ingroup fitpanel
15
16
17Allows to perform, explore and compare various fits.
18
19To display the new Fit panel interface right click on a histogram
20or a graph to pop up the context menu and then select the menu
21entry 'Fit Panel'.
22
23"General" Tab
24
25The first set of GUI elements is related to the function choice
26and settings. The status bar on the bottom provides information
27about the current minimization settings using the following
28abbreviations:
29LIB - shows the current choice between Minuit/Minuit2/Fumili
30MIGRAD or FUMILI points to the current minimization method in use.
31Itr: - shows the maximum number of iterations nnnn set for the fit.
32Prn: - can be DEF/VER/QT and shows the current print option in use.
33
34"Predefined" combo box - contains a list of predefined functions
35in ROOT. The default one is Gaussian.
36
37"Operation" radio button group defines selected operational mode
38between functions: NOP - no operation (default); ADD - addition
39CONV - convolution (will be implemented in the future).
40
41Users can enter the function expression in a text entry field.
42The entered string is checked after Enter key was pressed. An
43error message shows up if the string is not accepted. The current
44prototype is limited and users have no freedom to enter file/user
45function names in this field.
46
47"Set Parameters" button opens a dialog for parameters settings.
48
49"Fit Settings" provides user interface elements related to the
50fitter. Currently there are two method choices: Chi-square and
51Binned Likelihood.
52
53"Linear Fit" check button sets the use of Linear fitter is it is
54selected. Otherwise the option 'F' is applied if polN is selected.
55"Robust" number entry sets the robust value when fitting graphs.
56"No Chi-square" check button sets ON/OFF option 'C' - do not
57calculate Chi-square (for Linear fitter).
58
59Fit options:
60"Integral" check button switch ON/OFF option 'I' - use integral
61of function instead of value in bin center.
62"Best Errors" sets ON/OFF option 'E' - better errors estimation
63using Minos technique.
64"All weights = 1" sets ON/OFF option 'W' - all weights set to 1,
65excluding empty bins and ignoring error bars.
66"Empty bins, weights=1" sets ON/OFF option 'WW' - all weights
67equal to 1, including empty bins, error bars ignored.
68"Use range" sets ON/OFF option 'R' - fit only data within the
69specified function range with the slider.
70"Improve fit results" sets ON/OFF option 'M' - after minimum is
71found, search for a new one.
72"Add to list" sets On/Off option '+'- add function to the list
73without deleting the previous.
74
75Draw options:
76"SAME" sets On/Off function drawing on the same pad.
77"No drawing" sets On/Off option '0'- do not draw function graphics.
78"Do not store/draw" sets On/Off option 'N'- do not store the
79function, do not draw it.
80
81Sliders settings are used if option 'R' - use range is active.
82Users can change min/max values by pressing the left mouse button
83near to the left/right slider edges. It is possible o change both
84values simultaneously by pressing the left mouse button near to its
85center and moving it to a new desire position.
86
87"Minimization" Tab
88
89"Library" group allows you to use Minuit, Minuit2 or Fumili
90minimization packages for your fit.
91 "Minuit" - the popular Minuit minimization package.
92 "Minuit2" - a new object-oriented implementation of Minuit in C++.
93 "Fumili" - the popular Fumili minimization package.
94
95"Method" group has currently restricted functionality.
96 "MIGRAD" method is available for Minuit and Minuit2
97 "FUMILI" method is available for Fumili and Minuit2
98 "SIMPLEX" method is disabled (will come with the new fitter design)
99
100"Minimization Settings' group allows users to set values for:
101 "Error definition" - between 0.0 and 100.0 (default is 1.0).
102 "Maximum tolerance" - the fit relative precision in use.
103 "Maximum number of iterations" - default is 5000.
104
105Print options:
106 "Default" - between Verbose and Quiet.
107 "Verbose" - prints results after each iteration.
108 "Quiet" - no fit information is printed.
109
110Fit button - performs a fit.
111Reset - resets all GUI elements and related fit settings to the
112default ones.
113Close - closes this window.
114
115*/
116
117
118#include "TFitEditor.h"
119#include "TROOT.h"
120#include "TClass.h"
121#include "TCanvas.h"
122#include "TGTab.h"
123#include "TGLabel.h"
124#include "TG3DLine.h"
125#include "TGComboBox.h"
126#include "TGTextEntry.h"
127#include "TGGC.h"
128#include "TGButtonGroup.h"
129#include "TGNumberEntry.h"
130#include "TGDoubleSlider.h"
131#include "TGStatusBar.h"
132#include "TFitParametersDialog.h"
133#include "TGMsgBox.h"
134#include "TAxis.h"
135#include "TGraph.h"
136#include "TGraph2D.h"
137#include "TH1.h"
138#include "TH2.h"
139#include "HFitInterface.h"
140#include "TF1.h"
141#include "TF1NormSum.h"
142#include "TF1Convolution.h"
143#include "TF2.h"
144#include "TF3.h"
145#include "THStack.h"
146#include "Fit/UnBinData.h"
147#include "Fit/BinData.h"
148#include "TMultiGraph.h"
149#include "TTree.h"
150#include "TVirtualTreePlayer.h"
151#include "TSelectorDraw.h"
152#include "TTreeInput.h"
154#include "TVirtualX.h"
155#include "strlcpy.h"
156
157#include "RConfigure.h"
158#include "TPluginManager.h"
159
160#include <vector>
161#include <queue>
162using std::vector;
163using std::pair;
164
165#include "CommonDefs.h"
166
167// #include <iostream>
168// using std::cout;
169// using std::endl;
170
171void SearchCanvases(TSeqCollection* canvases, std::vector<TObject*>& objects);
172
173typedef std::multimap<TObject*, TF1*> FitFuncMap_t;
174
175////////////////////////////////////////////////////////////////////////////////
176/// This method looks among the functions stored by the fitpanel, the
177/// one that is currently selected in the fFuncList
178
180{
181 // Get the title/name of the function from fFuncList
183 if ( !te ) return 0;
184 TString name(te->GetTitle());
185
186 // Look for a system function if it's USER DEFINED function
187 if ( fTypeFit->GetSelected() == kFP_UFUNC ) {
188 for (auto f : fSystemFuncs) {
189 if ( strcmp( f->GetName(), name ) == 0 )
190 // If found, return it.
191 return f;
192 }
193 // If we are looking for previously fitted functions, look in the
194 // fPrevFit data structure.
195 } else if ( fTypeFit->GetSelected() == kFP_PREVFIT ) {
196 std::pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(fFitObject);
197 for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
198 TF1* f = it->second;
199 if ( strcmp( f->GetName(), name ) == 0 )
200 // If found, return it
201 return f;
202 }
203 }
204
205 // Return a pointer to null if the function does not exist. This
206 // will eventually create a segmentation fault, but the line should
207 // never be executed.
208 return 0;
209}
210
211////////////////////////////////////////////////////////////////////////////////
212///Copies f into a new TF1 to be stored in the fitpanel with it's
213///own ownership. This is taken from Fit::StoreAndDrawFitFunction in
214///HFitImpl.cxx
215
217{
218 double xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;
219
220 // no need to use kNotGlobal bit. TF1::Copy does not add in the list by default
221 if ( dynamic_cast<TF3 *>(f) != 0 ) {
222 TF3* fnew = (TF3 *)f->IsA()->New();
223 f->Copy(*fnew);
224 f->GetRange(xmin,ymin,zmin,xmax,ymax,zmax);
225 fnew->SetRange(xmin,ymin,zmin,xmax,ymax,zmax);
226 fnew->SetParent( nullptr );
227 fnew->AddToGlobalList(false);
228 return fnew;
229 } else if ( dynamic_cast<TF2 *>(f) != 0 ) {
230 TF2* fnew = (TF2 *)f->IsA()->New();
231 f->Copy(*fnew);
232 f->GetRange(xmin,ymin,xmax,ymax);
233 fnew->SetRange(xmin,ymin,xmax,ymax);
234 fnew->Save(xmin,xmax,ymin,ymax,0,0);
235 fnew->SetParent( nullptr );
236 fnew->AddToGlobalList(false);
237 return fnew;
238 } else {
239 TF1* fnew = (TF1 *)f->IsA()->New();
240 f->Copy(*fnew);
241 f->GetRange(xmin,xmax);
242 fnew->SetRange(xmin,xmax);
243 // This next line is added, as fnew-Save fails with gausND! As
244 // the number of dimensions is unknown...
245 if ( '\0' != fnew->GetExpFormula()[0] )
246 fnew->Save(xmin,xmax,0,0,0,0);
247 fnew->SetParent( nullptr );
248 fnew->AddToGlobalList(false);
249 return fnew;
250 }
251}
252
253////////////////////////////////////////////////////////////////////////////////
254/// Stores the parameters of the given function into pars
255
257{
258 int npar = func->GetNpar();
259 if (npar != (int) pars.size() ) pars.resize(npar);
260 for ( Int_t i = 0; i < npar; ++i )
261 {
262 Double_t par_min, par_max;
263 pars[i][PAR_VAL] = func->GetParameter(i);
264 func->GetParLimits(i, par_min, par_max);
265 pars[i][PAR_MIN] = par_min;
266 pars[i][PAR_MAX] = par_max;
267 }
268}
269
270////////////////////////////////////////////////////////////////////////////////
271/// Restore the parameters from pars into the function
272
274{
275 int npar = func->GetNpar();
276 if (npar > (int) pars.size() ) pars.resize(npar);
277 for ( Int_t i = 0; i < npar; ++i )
278 {
279 func->SetParameter(i, pars[i][PAR_VAL]);
280 func->SetParLimits(i, pars[i][PAR_MIN], pars[i][PAR_MAX]);
281 }
282}
283
284////////////////////////////////////////////////////////////////////////////////
285/// Parameter initialization for the function
286
287template<class FitObject>
288void InitParameters(TF1* func, FitObject * fitobj)
289{
290 const int special = func->GetNumber();
291 if (100 == special || 400 == special) {
293 ROOT::Fit::FillData(data,fitobj,func);
294 ROOT::Fit::InitGaus(data, func);
295 // case gaussian or Landau
296 } else if ( 110 == special || 410 == special ) {
298 ROOT::Fit::FillData(data,fitobj,func);
299 ROOT::Fit::Init2DGaus(data,func);
300 }
301}
302
303////////////////////////////////////////////////////////////////////////////////
304/// Splits the entry in fDataSet to get the selected variables and cuts
305/// from the text.
306
307void GetTreeVarsAndCuts(TGComboBox* dataSet, TString& variablesStr, TString& cutsStr)
308{
309 // Get the entry
310 TGTextLBEntry* textEntry =
311 static_cast<TGTextLBEntry*>( dataSet->GetListBox()->GetEntry( dataSet->GetSelected() ) );
312 if (!textEntry) return;
313 // Get the name of the tree
314 TString nameStr ( textEntry->GetText()->GetString() );
315 // Get the variables selected
316 variablesStr = nameStr(nameStr.First('(') + 2, nameStr.First(',') - nameStr.First('(') - 3);
317 // Get the cuts selected
318 cutsStr = nameStr( nameStr.First(',') + 3, nameStr.First(')') - nameStr.First(',') - 4 );
319}
320
321
323
325
326////////////////////////////////////////////////////////////////////////////////
327/// Static method - opens the fit panel.
328
330{
331 // Get the default pad if not provided.
332 if (!pad)
333 {
334 if (!gPad)
335 gROOT->MakeDefCanvas();
336 pad = gPad;
337 }
338
339 if (!fgFitDialog) {
340 fgFitDialog = new TFitEditor(pad, obj);
341 } else {
342 fgFitDialog->Show(pad, obj);
343 }
344 return fgFitDialog;
345}
346
347////////////////////////////////////////////////////////////////////////////////
348/// Constructor of fit editor. 'obj' is the object to be fitted and
349/// 'pad' where it is drawn.
350
352 TGMainFrame(gClient->GetRoot(), 20, 20),
353 fParentPad (0),
354 fFitObject (0),
355 fDim (0),
356 fXaxis (0),
357 fYaxis (0),
358 fZaxis (0),
359 fSumFunc (0),
360 fConvFunc (0),
361 fFuncPars (0),
362 fChangedParams (kFALSE)
363{
366
367 TGCompositeFrame *tf = new TGCompositeFrame(this, 350, 26,
369 TGLabel *label = new TGLabel(tf,"Data Set: ");
370 tf->AddFrame(label, new TGLayoutHints(kLHintsNormal, 15, 0, 5, 0));
371
372 fDataSet = new TGComboBox(tf, kFP_DATAS);
374 fDataSet->Resize(264, 20);
375
376 tf->AddFrame(fDataSet, new TGLayoutHints(kLHintsNormal, 13, 0, 5, 0));
377 fDataSet->Associate(this);
378
379 this->AddFrame(tf, new TGLayoutHints(kLHintsNormal | kLHintsExpandX,0,0,5,5));
380
382
383 fTab = new TGTab(this, 10, 10);
386 fTab->Associate(this);
387
388 TGHorizontalFrame *cf1 = new TGHorizontalFrame(this, 350, 20, kFixedWidth);
390 fUpdateButton = new TGTextButton(cf1, "&Update", kFP_UPDATE);
393 kLHintsExpandX, 0, 20, 2, 2));
394
395
396 fFitButton = new TGTextButton(cf1, "&Fit", kFP_FIT);
397 fFitButton->Associate(this);
399 kLHintsExpandX, 15, -6, 2, 2));
400
401 fResetButton = new TGTextButton(cf1, "&Reset", kFP_RESET);
402 fResetButton->Associate(this);
404 kLHintsExpandX, 11, -2, 2, 2));
405
406 fCloseButton = new TGTextButton(cf1, "&Close", kFP_CLOSE);
407 fCloseButton->Associate(this);
409 kLHintsExpandX, 7, 2, 2, 2));
411 kLHintsRight, 0, 5, 5, 5));
412
413 // Create status bar
414 int parts[] = { 20, 20, 20, 20, 20 };
415 fStatusBar = new TGStatusBar(this, 10, 10);
416 fStatusBar->SetParts(parts, 5);
420
423
424 gROOT->GetListOfCleanups()->Add(this);
425
428
429 // do not allow resizing
431 SetWindowName("Fit Panel");
432 SetIconName("Fit Panel");
433 SetClassHints("ROOT", "Fit Panel");
434
440
441 ConnectSlots();
442
444
445 if (!obj) {
446 TList* l = new TList();
447 l->Add(pad);
448 std::vector<TObject*> v;
450 if ( v.size() )
451 obj = v[0];
452 delete l;
453 }
454
455 SetFitObject(pad, obj, kButton1Down);
456
457 // In case we want to make it without a default canvas. This will
458 // be implemented after the 5.21/06 Release. Remember to take out
459 // any reference to the pad/canvas when the fitpanel is shown
460 // and/or built.
461
462 //SetCanvas(0 /*pad->GetCanvas()*/);
463
464 if ( pad ) {
465 SetCanvas(pad->GetCanvas());
466 if ( obj )
467 pad->GetCanvas()->Selected(pad, obj, kButton1Down);
468 }
469
471 UInt_t cw = 0;
472 UInt_t cx = 0;
473 UInt_t cy = 0;
474 if (pad && pad->GetCanvas() ) {
475 cw = pad->GetCanvas()->GetWindowWidth();
476 cx = (UInt_t)pad->GetCanvas()->GetWindowTopX();
477 cy = (UInt_t)pad->GetCanvas()->GetWindowTopY();
478 }
479
480 Resize(size);
481 MapWindow();
482
483 if (cw + size.fWidth < dw) {
484 Int_t gedx = 0, gedy = 0;
485 gedx = cx+cw+4;
486 gedy = (cy > 20) ? cy-20 : 0;
487 MoveResize(gedx, gedy, size.fWidth, size.fHeight);
488 SetWMPosition(gedx, gedy);
489 }
490
491 gVirtualX->RaiseWindow(GetId());
492
494 SetWMSize(size.fWidth, size.fHeight);
495 SetWMSizeHints(size.fWidth, size.fHeight, size.fWidth, size.fHeight, 0, 0);
496}
497
498////////////////////////////////////////////////////////////////////////////////
499/// Fit editor destructor.
500
502{
504
505 // Disconnect all the slot that were no disconnected in DisconnecSlots
506 fCloseButton ->Disconnect("Clicked()");
507 fDataSet ->Disconnect("Selected(Int_t)");
508 fUpdateButton->Disconnect("Clicked()");
509 TQObject::Disconnect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)",
510 this, "SetFitObject(TVirtualPad *, TObject *, Int_t)");
511 gROOT->GetListOfCleanups()->Remove(this);
512
513 //Clean up the members that are not automatically cleaned.
514 Cleanup();
515 delete fLayoutNone;
516 delete fLayoutAdd;
517 delete fLayoutConv;
518
519 if (fConvFunc) delete fConvFunc;
520 if (fSumFunc) delete fSumFunc;
521
522 // release memory used by stored functions of previous fits
523 for (auto &entry : fPrevFit)
524 delete entry.second;
525 fPrevFit.clear();
526
527 // release memory used by copies of system functions
528 for (auto func : fSystemFuncs)
529 delete func;
530 fSystemFuncs.clear();
531
532 // Set the singleton reference to null
533 fgFitDialog = 0;
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// Creates the Frame that contains oll the information about the
538/// function.
539
541{
542 TGGroupFrame *gf1 = new TGGroupFrame(this, "Fit Function", kFitWidth);
543 TGCompositeFrame *tf0 = new TGCompositeFrame(gf1, 350, 26, kHorizontalFrame);
544 TGLabel *label1 = new TGLabel(tf0,"Type:");
545 tf0 -> AddFrame(label1, new TGLayoutHints(kLHintsNormal, 0, 0, 5, 0));
546
547 fTypeFit = new TGComboBox(tf0, kFP_TLIST);
548 fTypeFit -> AddEntry("User Func", kFP_UFUNC);
549 fTypeFit -> AddEntry("Predef-1D", kFP_PRED1D);
550 fTypeFit -> Resize(90, 20);
551 fTypeFit -> Select(kFP_PRED1D, kFALSE);
552
554 lb->Resize(lb->GetWidth(), 200);
555 tf0->AddFrame(fTypeFit, new TGLayoutHints(kLHintsNormal, 5, 0, 5, 0));
556 fTypeFit->Associate(this);
557
558 fFuncList = new TGComboBox(tf0, kFP_FLIST);
560 fFuncList->Resize(194, 20);
562
563 lb = fFuncList->GetListBox();
564 lb -> Resize(lb->GetWidth(), 500);
565 tf0 -> AddFrame(fFuncList, new TGLayoutHints(kLHintsNormal, 5, 0, 5, 0));
566 fFuncList->Associate(this);
567
569
570 TGCompositeFrame *tf1 = new TGCompositeFrame(gf1, 350, 26, kHorizontalFrame);
571 TGHButtonGroup *bgr = new TGHButtonGroup(tf1, "Operation");
572
573 bgr -> SetRadioButtonExclusive();
574 fNone = new TGRadioButton(bgr, "Nop", kFP_NONE);
575 fAdd = new TGRadioButton(bgr, "Add", kFP_ADD);
576 fNormAdd = new TGRadioButton(bgr, "NormAdd", kFP_NORMADD);
577 fConv = new TGRadioButton(bgr, "Conv", kFP_CONV);
578
579 fNone -> SetToolTipText("No operation defined");
580 fNone -> SetState(kButtonDown, kFALSE);
581 fAdd -> SetToolTipText("Addition");
582 // fAdd -> SetState(kButtonDown, kFALSE);
583 fNormAdd -> SetToolTipText("NormAddition");
584 //fNormAdd -> SetState(kButtonDown, kFALSE);
585 fConv -> SetToolTipText("Convolution");
586 //fConv -> SetState(kButtonDown, kTRUE);
587
588 fLayoutNone = new TGLayoutHints(kLHintsLeft,0 ,5,3,-10);
589 fLayoutAdd = new TGLayoutHints(kLHintsLeft,10,5,3,-10);
590 fLayoutNormAdd = new TGLayoutHints(kLHintsLeft,10,5,3,-10);
591 fLayoutConv = new TGLayoutHints(kLHintsLeft,10,5,3,-10);
592
593 bgr -> SetLayoutHints(fLayoutNone, fNone);
594 bgr -> SetLayoutHints(fLayoutAdd, fAdd);
595 bgr -> SetLayoutHints(fLayoutNormAdd,fNormAdd);
596 bgr -> SetLayoutHints(fLayoutConv, fConv);
597 bgr -> Show();
599
600 tf1 -> AddFrame(bgr, new TGLayoutHints(kLHintsExpandX, 0, 0, 3, 0));
601 gf1 -> AddFrame(tf1, new TGLayoutHints(kLHintsExpandX));
602
603 TGCompositeFrame *tf2 = new TGCompositeFrame(gf1, 350, 26,
605 fEnteredFunc = new TGTextEntry(tf2, new TGTextBuffer(0), kFP_FILE);
606 //fEnteredFunc->SetMaxLength(4000); // use default value (~4000)
609 assert(te);
611 fEnteredFunc->SetToolTipText("Enter file_name/function_name or a function expression");
615 kLHintsExpandX, 2, 2, 2, 2));
616 gf1->AddFrame(tf2, new TGLayoutHints(kLHintsNormal |
617 kLHintsExpandX, 0, 0, 2, 0));
618
620 TGLabel *label21 = new TGLabel(s1, "Selected: ");
621 s1->AddFrame(label21, new TGLayoutHints(kLHintsNormal |
622 kLHintsCenterY, 2, 2, 2, 0));
624 s1->AddFrame(hlines, new TGLayoutHints(kLHintsCenterY | kLHintsExpandX));
626
627 TGCompositeFrame *tf4 = new TGCompositeFrame(gf1, 350, 26,
630 TString s = txt->GetTitle();
631 fSelLabel = new TGLabel(tf4, s.Sizeof()>30?s(0,30)+"...":s);
633 kLHintsCenterY, 0, 6, 2, 0));
634 Pixel_t color;
635 gClient->GetColorByName("#336666", color);
637 TGCompositeFrame *tf5 = new TGCompositeFrame(tf4, 120, 20,
639 fSetParam = new TGTextButton(tf5, "Set Parameters...", kFP_PARS);
643 fSetParam->SetToolTipText("Open a dialog for parameter(s) settings");
644 tf4->AddFrame(tf5, new TGLayoutHints(kLHintsRight |
645 kLHintsTop, 5, 0, 2, 2));
646 gf1->AddFrame(tf4, new TGLayoutHints(kLHintsNormal |
647 kLHintsExpandX, 5, 0, 0, 0));
648
649 this->AddFrame(gf1, new TGLayoutHints(kLHintsExpandX, 5, 5, 0, 0));
650
651}
652
653////////////////////////////////////////////////////////////////////////////////
654/// Create 'General' tab.
655
657{
658 fTabContainer = fTab->AddTab("General");
662 5, 5, 2, 2));
663
664 // 'options' group frame
665 TGGroupFrame *gf = new TGGroupFrame(fGeneral, "Fit Settings", kFitWidth);
666
667 // 'method' sub-group
669 TGLabel *label4 = new TGLabel(h1, "Method");
670 h1->AddFrame(label4, new TGLayoutHints(kLHintsNormal |
671 kLHintsCenterY, 2, 2, 0, 0));
673 h1->AddFrame(hline1, new TGLayoutHints(kLHintsCenterY | kLHintsExpandX));
675
680 fMethodList->Resize(140, 20);
682 Int_t lbe = lb->GetNumberOfEntries();
683 lb->Resize(lb->GetWidth(), lbe*16);
684 v1->AddFrame(fMethodList, new TGLayoutHints(kLHintsLeft, 0, 0, 2, 5));
685
686 fLinearFit = new TGCheckButton(v1, "Linear fit", kFP_MLINF);
687 fLinearFit->Associate(this);
688 fLinearFit->SetToolTipText("Perform Linear fitter if selected");
689 v1->AddFrame(fLinearFit, new TGLayoutHints(kLHintsNormal, 0, 0, 8, 2));
690
691
693
695 TGCompositeFrame *v21 = new TGCompositeFrame(v2, 120, 20,
697 fUserButton = new TGTextButton(v21, "User-Defined...", kFP_MUSR);
701 fUserButton->SetToolTipText("Open a dialog for entering a user-defined method");
703 v2->AddFrame(v21, new TGLayoutHints(kLHintsRight | kLHintsTop));
704
706 fEnableRobust = new TGCheckButton(v1h, "Robust:", -1);
707 fEnableRobust->Associate(this); // needed ???
708 fEnableRobust->SetToolTipText("Perform Linear Robust fitter if selected");
709 v1h->AddFrame(fEnableRobust, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
710 fRobustValue = new TGNumberEntry(v1h, 0.95, 5, kFP_RBUST,
715 v2->AddFrame(v1h, new TGLayoutHints(kLHintsNormal, 0, 0, 12, 2));
717 fRobustValue->GetNumberEntry()->SetToolTipText("Available only for graphs");
718
719 fNoChi2 = 0;
720 // fNoChi2 = new TGCheckButton(v2, "No Chi-square", kFP_NOCHI);
721 // fNoChi2->Associate(this);
722 // fNoChi2->SetToolTipText("'C'- do not calculate Chi-square (for Linear fitter)");
723 // v2->AddFrame(fNoChi2, new TGLayoutHints(kLHintsNormal, 0, 0, 34, 2));
724
725 h2->AddFrame(v2, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 20, 0, 0, 0));
726 gf->AddFrame(h2, new TGLayoutHints(kLHintsExpandX, 20, 0, 0, 0));
727
728 // 'fit option' sub-group
730 TGLabel *label5 = new TGLabel(h3, "Fit Options");
731 h3->AddFrame(label5, new TGLayoutHints(kLHintsNormal |
732 kLHintsCenterY, 2, 2, 0, 0));
733 TGHorizontal3DLine *hline2 = new TGHorizontal3DLine(h3);
736
739 fIntegral = new TGCheckButton(v3, "Integral", kFP_INTEG);
740 fIntegral->Associate(this);
741 fIntegral->SetToolTipText("'I'- use integral of function instead of value in bin center");
742 v3->AddFrame(fIntegral, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
743
744 fBestErrors = new TGCheckButton(v3, "Best errors", kFP_IMERR);
745 fBestErrors->Associate(this);
746 fBestErrors->SetToolTipText("'E'- better errors estimation using Minos technique");
747 v3->AddFrame(fBestErrors, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
748
749 fAllWeights1 = new TGCheckButton(v3, "All weights = 1", kFP_ALLW1);
750 fAllWeights1->Associate(this);
751 fAllWeights1->SetToolTipText("'W'- all weights=1 for non empty bins; error bars ignored");
752 v3->AddFrame(fAllWeights1, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
753
754 fEmptyBinsWghts1 = new TGCheckButton(v3, "Empty bins, weights=1", kFP_EMPW1);
756 fEmptyBinsWghts1->SetToolTipText("'WW'- all weights=1 including empty bins; error bars ignored");
757 v3->AddFrame(fEmptyBinsWghts1, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
758
760
762 fUseRange = new TGCheckButton(v4, "Use range", kFP_USERG);
763 fUseRange->Associate(this);
764 fUseRange->SetToolTipText("'R'- fit only data within the specified function range");
765 v4->AddFrame(fUseRange, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
766
767 fImproveResults = new TGCheckButton(v4, "Improve fit results", kFP_IFITR);
769 fImproveResults->SetToolTipText("'M'- after minimum is found, search for a new one");
770 v4->AddFrame(fImproveResults, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
771
772 fAdd2FuncList = new TGCheckButton(v4, "Add to list", kFP_ADDLS);
774 fAdd2FuncList->SetToolTipText("'+'- add function to the list without deleting the previous");
775 v4->AddFrame(fAdd2FuncList, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
776
777 fUseGradient = new TGCheckButton(v4, "Use Gradient", kFP_ADDLS);
778 fUseGradient->Associate(this);
779 fUseGradient->SetToolTipText("'G'- Use the gradient as an aid for the fitting");
780 v4->AddFrame(fUseGradient, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
781
782 h->AddFrame(v4, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 20, 0, 0, 0));
783 gf->AddFrame(h, new TGLayoutHints(kLHintsExpandX, 20, 0, 0, 0));
784
785 // 'draw option' sub-group
787 TGLabel *label6 = new TGLabel(h5, "Draw Options");
788 h5->AddFrame(label6, new TGLayoutHints(kLHintsNormal |
789 kLHintsCenterY, 2, 2, 2, 2));
790 TGHorizontal3DLine *hline3 = new TGHorizontal3DLine(h5);
793
795 TGVerticalFrame *v5 = new TGVerticalFrame(h6);
796
797 fDrawSame = new TGCheckButton(v5, "SAME", kFP_DSAME);
798 fDrawSame->Associate(this);
799 fDrawSame->SetToolTipText("Superimpose on previous picture in the same pad");
800 v5->AddFrame(fDrawSame, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
801
802 fNoDrawing = new TGCheckButton(v5, "No drawing", kFP_DNONE);
803 fNoDrawing->Associate(this);
804 fNoDrawing->SetToolTipText("'0'- do not draw function graphics");
805 v5->AddFrame(fNoDrawing, new TGLayoutHints(kLHintsNormal, 0, 0, 2, 2));
806
807 fNoStoreDrawing = new TGCheckButton(v5, "Do not store/draw", kFP_DNOST);
809 fNoStoreDrawing->SetToolTipText("'N'- do not store the function, do not draw it");
811
813
814 TGVerticalFrame *v6 = new TGVerticalFrame(h6);
815 TGCompositeFrame *v61 = new TGCompositeFrame(v6, 120, 20,
817 fDrawAdvanced = new TGTextButton(v61, "&Advanced...", kFP_DADVB);
821 fDrawAdvanced->SetToolTipText("Open a dialog for advanced draw options");
823
825 0, 0, (4+fDrawSame->GetHeight())*2, 0));
826
828 gf->AddFrame(h6, new TGLayoutHints(kLHintsExpandX, 20, 0, 2, 0));
829
831 kLHintsExpandY, 5, 5, 0, 0));
832 // sliderX
834 TGLabel *label8 = new TGLabel(fSliderXParent, "X");
836 kLHintsCenterY, 0, 5, 0, 0));
837
843
845 fSliderX->SetScale(5);
847
848
855
856 // sliderY
858 TGLabel *label9 = new TGLabel(fSliderYParent, "Y");
860 kLHintsCenterY, 0, 5, 0, 0));
861
867
869 fSliderY->SetScale(5);
871
878
879 // sliderZ
881 TGLabel *label10 = new TGLabel(fSliderZParent, "Z:");
883 kLHintsCenterY, 0, 5, 0, 0));
885 fSliderZ->SetScale(5);
889}
890
891
892////////////////////////////////////////////////////////////////////////////////
893/// Create 'Minimization' tab.
894
896{
897 fTabContainer = fTab->AddTab("Minimization");
901 5, 5, 2, 2));
902 MakeTitle(fMinimization, "Library");
903
905 fLibMinuit = new TGRadioButton(hl, "Minuit", kFP_LMIN);
906 fLibMinuit->Associate(this);
907 fLibMinuit->SetToolTipText("Use minimization from libMinuit (default)");
908 hl->AddFrame(fLibMinuit, new TGLayoutHints(kLHintsNormal, 40, 0, 0, 1));
909 fStatusBar->SetText("LIB Minuit",1);
910
911 fLibMinuit2 = new TGRadioButton(hl, "Minuit2", kFP_LMIN2);
912 fLibMinuit2->Associate(this);
913 fLibMinuit2->SetToolTipText("New C++ version of Minuit");
914 hl->AddFrame(fLibMinuit2, new TGLayoutHints(kLHintsNormal, 35, 0, 0, 1));
915
916 fLibFumili = new TGRadioButton(hl, "Fumili", kFP_LFUM);
917 fLibFumili->Associate(this);
918 fLibFumili->SetToolTipText("Use minimization from libFumili");
919 hl->AddFrame(fLibFumili, new TGLayoutHints(kLHintsNormal, 30, 0, 0, 1));
920 fMinimization->AddFrame(hl, new TGLayoutHints(kLHintsExpandX, 20, 0, 5, 1));
921
923
924 fLibGSL = new TGRadioButton(hl2, "GSL", kFP_LGSL);
925 #ifdef R__HAS_MATHMORE
926 fLibGSL->Associate(this);
927 fLibGSL->SetToolTipText("Use minimization from libGSL");
928 #else
930 fLibGSL->SetToolTipText("Needs GSL to be compiled");
931 #endif
932 hl2->AddFrame(fLibGSL, new TGLayoutHints(kLHintsNormal, 40, 0, 0, 1));
933
934 fLibGenetics = new TGRadioButton(hl2, "Genetics", kFP_LGAS);
935 if (gPluginMgr->FindHandler("ROOT::Math::Minimizer","Genetic") ||
936 gPluginMgr->FindHandler("ROOT::Math::Minimizer","GAlibMin") )
937 {
938 fLibGenetics->Associate(this);
939 fLibGenetics->SetToolTipText("Different GAs implementations");
940 } else {
942 fLibGenetics->SetToolTipText("Needs any of the genetic"
943 "minimizers to be compiled");
944 }
945 hl2->AddFrame(fLibGenetics, new TGLayoutHints(kLHintsNormal, 45, 0, 0, 1));
946
947 fMinimization->AddFrame(hl2, new TGLayoutHints(kLHintsExpandX, 20, 0, 5, 1));
948
949 MakeTitle(fMinimization, "Method");
950
953 fMinMethodList->Resize(290, 20);
955
957 lb->Resize(lb->GetWidth(), 500);
959
961 fMinimization->AddFrame(hm0, new TGLayoutHints(kLHintsExpandX, 60, 0, 5, 1));
962
963 // Set the status to the default minimization options!
966 } else if ( ROOT::Math::MinimizerOptions::DefaultMinimizerType() == "Minuit" ) {
968 } else {
970 }
972
973 MakeTitle(fMinimization, "Settings");
974 TGLabel *hslabel1 = new TGLabel(fMinimization,"Use ENTER key to validate a new value or click");
975 fMinimization->AddFrame(hslabel1, new TGLayoutHints(kLHintsNormal, 61, 0, 5, 1));
976 TGLabel *hslabel2 = new TGLabel(fMinimization,"on Reset button to set the defaults.");
977 fMinimization->AddFrame(hslabel2, new TGLayoutHints(kLHintsNormal, 61, 0, 1, 10));
978
980
981 TGVerticalFrame *hsv1 = new TGVerticalFrame(hs, 180, 10, kFixedWidth);
982 TGLabel *errlabel = new TGLabel(hsv1,"Error definition (default = 1): ");
983 hsv1->AddFrame(errlabel, new TGLayoutHints(kLHintsLeft | kLHintsCenterY,
984 1, 1, 5, 7));
985 TGLabel *tollabel = new TGLabel(hsv1,"Max tolerance (precision): ");
986 hsv1->AddFrame(tollabel, new TGLayoutHints(kLHintsLeft | kLHintsCenterY,
987 1, 1, 5, 7));
988 TGLabel *itrlabel = new TGLabel(hsv1,"Max number of iterations: ");
989 hsv1->AddFrame(itrlabel, new TGLayoutHints(kLHintsLeft | kLHintsCenterY,
990 1, 1, 5, 5));
991 hs->AddFrame(hsv1, new TGLayoutHints(kLHintsNormal, 60, 0, 0, 0));
992
993 TGVerticalFrame *hsv2 = new TGVerticalFrame(hs, 90,10, kFixedWidth);
999 1, 1, 0, 3));
1006 1, 1, 3, 3));
1007 fIterations = new TGNumberEntryField(hsv2, kFP_MITR, 5000,
1013 1, 1, 3, 3));
1014 hs->AddFrame(hsv2, new TGLayoutHints(kLHintsNormal, 0, 0, 0, 0));
1015 fMinimization->AddFrame(hs, new TGLayoutHints(kLHintsExpandX, 0, 0, 1, 1));
1017
1018 MakeTitle(fMinimization, "Print Options");
1019
1021 fOptDefault = new TGRadioButton(h8, "Default", kFP_PDEF);
1022 fOptDefault->Associate(this);
1023 fOptDefault->SetToolTipText("Default is between Verbose and Quiet");
1024 h8->AddFrame(fOptDefault, new TGLayoutHints(kLHintsNormal, 40, 0, 0, 1));
1026 fStatusBar->SetText("Prn: DEF",4);
1027
1028 fOptVerbose = new TGRadioButton(h8, "Verbose", kFP_PVER);
1029 fOptVerbose->Associate(this);
1030 fOptVerbose->SetToolTipText("'V'- print results after each iteration");
1031 h8->AddFrame(fOptVerbose, new TGLayoutHints(kLHintsNormal, 30, 0, 0, 1));
1032
1033 fOptQuiet = new TGRadioButton(h8, "Quiet", kFP_PQET);
1034 fOptQuiet->Associate(this);
1035 fOptQuiet->SetToolTipText("'Q'- no print");
1036 h8->AddFrame(fOptQuiet, new TGLayoutHints(kLHintsNormal, 25, 0, 0, 1));
1037
1038 fMinimization->AddFrame(h8, new TGLayoutHints(kLHintsExpandX, 20, 0, 5, 1));
1039
1040}
1041
1042////////////////////////////////////////////////////////////////////////////////
1043/// Connect GUI signals to fit panel slots.
1044
1046{
1047 // list of data sets to fit
1048 fDataSet -> Connect("Selected(Int_t)", "TFitEditor", this, "DoDataSet(Int_t)");
1049 // list of predefined functions
1050 fTypeFit -> Connect("Selected(Int_t)", "TFitEditor", this, "FillFunctionList(Int_t)");
1051 // list of predefined functions
1052 fFuncList -> Connect("Selected(Int_t)", "TFitEditor", this, "DoFunction(Int_t)");
1053 // entered formula or function name
1054 fEnteredFunc -> Connect("ReturnPressed()", "TFitEditor", this, "DoEnteredFunction()");
1055 // set parameters dialog
1056 fSetParam -> Connect("Clicked()", "TFitEditor", this, "DoSetParameters()");
1057 // allowed function operations
1058 fAdd -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoAddition(Bool_t)");
1059 //fNormAdd -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoNormAddition(Bool_t)");
1060 //fConv -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoConvolution(Bool_t)");
1061 // fit options
1062 fAllWeights1 -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoAllWeights1()");
1063 fUseRange -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoUseFuncRange()");
1064 fEmptyBinsWghts1 -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoEmptyBinsAllWeights1()");
1065 // linear fit
1066 fLinearFit -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoLinearFit()");
1067 fEnableRobust -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoRobustFit()");
1068 //fNoChi2->Connect("Toggled(Bool_t)","TFitEditor",this,"DoNoChi2()");
1069 // draw options
1070 fNoStoreDrawing -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoNoStoreDrawing()");
1071 // fit, reset, close buttons
1072 fUpdateButton -> Connect("Clicked()", "TFitEditor", this, "DoUpdate()");
1073 fFitButton -> Connect("Clicked()", "TFitEditor", this, "DoFit()");
1074 fResetButton -> Connect("Clicked()", "TFitEditor", this, "DoReset()");
1075 fCloseButton -> Connect("Clicked()", "TFitEditor", this, "DoClose()");
1076 // user method button
1077 fUserButton -> Connect("Clicked()", "TFitEditor", this, "DoUserDialog()");
1078 // advanced draw options
1079 fDrawAdvanced -> Connect("Clicked()", "TFitEditor", this, "DoAdvancedOptions()");
1080
1081 if (fType != kObjectTree)
1082 {
1083 fSliderX -> Connect("PositionChanged()","TFitEditor",this, "DoSliderXMoved()");
1084 fSliderXMax -> Connect("ValueSet(Long_t)", "TFitEditor",this, "DoNumericSliderXChanged()");
1085 fSliderXMin -> Connect("ValueSet(Long_t)", "TFitEditor",this, "DoNumericSliderXChanged()");
1086 }
1087 if (fDim > 1)
1088 {
1089 fSliderY -> Connect("PositionChanged()","TFitEditor",this, "DoSliderYMoved()");
1090 fSliderYMax -> Connect("ValueSet(Long_t)", "TFitEditor",this, "DoNumericSliderYChanged()");
1091 fSliderYMin -> Connect("ValueSet(Long_t)", "TFitEditor",this, "DoNumericSliderYChanged()");
1092 }
1093 if (fDim > 2)
1094 fSliderZ -> Connect("PositionChanged()","TFitEditor",this, "DoSliderZMoved()");
1095
1096 if ( fParentPad )
1097 fParentPad -> Connect("RangeAxisChanged()","TFitEditor",this, "UpdateGUI()");
1098 // 'Minimization' tab
1099 // library
1100 fLibMinuit -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoLibrary(Bool_t)");
1101 fLibMinuit2 -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoLibrary(Bool_t)");
1102 fLibFumili -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoLibrary(Bool_t)");
1103 fLibGSL -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoLibrary(Bool_t)");
1104 fLibGenetics -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoLibrary(Bool_t)");
1105
1106 // minimization method
1107 fMinMethodList -> Connect("Selected(Int_t)", "TFitEditor", this, "DoMinMethod(Int_t)");
1108 // fitter settings
1109 fIterations -> Connect("ReturnPressed()", "TFitEditor", this, "DoMaxIterations()");
1110 // print options
1111 fOptDefault -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoPrintOpt(Bool_t)");
1112 fOptVerbose -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoPrintOpt(Bool_t)");
1113 fOptQuiet -> Connect("Toggled(Bool_t)", "TFitEditor", this, "DoPrintOpt(Bool_t)");
1114
1115}
1116
1117////////////////////////////////////////////////////////////////////////////////
1118/// Disconnect GUI signals from fit panel slots.
1119
1121{
1122 Disconnect("CloseWindow()");
1123
1124 fFuncList -> Disconnect("Selected(Int_t)");
1125 fEnteredFunc -> Disconnect("ReturnPressed()");
1126 fSetParam -> Disconnect("Clicked()");
1127 fAdd -> Disconnect("Toggled(Bool_t)");
1128 // fNormAdd -> Disconnect("Toggled(Bool_t)");
1129 // fConv -> Disconnect("Toggled(Bool_t)");
1130
1131 // fit options
1132 fAllWeights1 -> Disconnect("Toggled(Bool_t)");
1133 fEmptyBinsWghts1 -> Disconnect("Toggled(Bool_t)");
1134
1135 // linear fit
1136 fLinearFit -> Disconnect("Toggled(Bool_t)");
1137 fEnableRobust -> Disconnect("Toggled(Bool_t)");
1138 //fNoChi2->Disconnect("Toggled(Bool_t)");
1139
1140 // draw options
1141 fNoStoreDrawing -> Disconnect("Toggled(Bool_t)");
1142
1143 // fit, reset, close buttons
1144 fFitButton -> Disconnect("Clicked()");
1145 fResetButton -> Disconnect("Clicked()");
1146
1147 // other methods
1148 fUserButton -> Disconnect("Clicked()");
1149 fDrawAdvanced -> Disconnect("Clicked()");
1150
1151 if (fType != kObjectTree)
1152 {
1153 fSliderX -> Disconnect("PositionChanged()");
1154 fSliderXMax -> Disconnect("ValueChanged(Long_t)");
1155 fSliderXMin -> Disconnect("ValueChanged(Long_t)");
1156 }
1157 if (fDim > 1)
1158 {
1159 fSliderY -> Disconnect("PositionChanged()");
1160 fSliderYMax -> Disconnect("ValueChanged(Long_t)");
1161 fSliderYMin -> Disconnect("ValueChanged(Long_t)");
1162 }
1163 if (fDim > 2)
1164 fSliderZ -> Disconnect("PositionChanged()");
1165 // slots related to 'Minimization' tab
1166 fLibMinuit -> Disconnect("Toggled(Bool_t)");
1167 fLibMinuit2 -> Disconnect("Toggled(Bool_t)");
1168 fLibFumili -> Disconnect("Toggled(Bool_t)");
1169 fLibGSL -> Disconnect("Toggled(Bool_t)");
1170 fLibGenetics -> Disconnect("Toggled(Bool_t)");
1171 // minimization method
1172 fMinMethodList -> Disconnect("Selected(Int_t)");
1173 // fitter settings
1174 fIterations -> Disconnect("ReturnPressed()");
1175 // print options
1176 fOptDefault -> Disconnect("Toggled(Bool_t)");
1177 fOptVerbose -> Disconnect("Toggled(Bool_t)");
1178 fOptQuiet -> Disconnect("Toggled(Bool_t)");
1179
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// Connect to another canvas.
1184
1186{
1187 // The next line is commented because it is stablishing a
1188 // connection with the particular canvas, while right the following
1189 // line will connect all the canvas in a general way.
1190
1191 // It would also make the fitpanel crash if there is no object
1192 // defined to be fitted in the construction (as a side effect of
1193 // it).
1194
1195// newcan->Connect("Selected(TVirtualPad*,TObject*,Int_t)", "TFitEditor",
1196// this, "SetFitObject(TVirtualPad *, TObject *, Int_t)");
1197
1198 TQObject::Connect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)",
1199 "TFitEditor",this,
1200 "SetFitObject(TVirtualPad *, TObject *, Int_t)");
1201 TQObject::Connect("TCanvas", "Closed()", "TFitEditor", this, "DoNoSelection()");
1202}
1203
1204////////////////////////////////////////////////////////////////////////////////
1205/// Hide the fit panel and set it to non-active state.
1206
1208{
1209 if (fgFitDialog) {
1211 }
1212 if (fParentPad) {
1213 fParentPad->Disconnect("RangeAxisChanged()");
1214 DoReset();
1215 TQObject::Disconnect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)",
1216 this, "SetFitObject(TVirtualPad *, TObject *, Int_t)");
1217 }
1218 fParentPad = 0;
1219 fFitObject = 0;
1220 gROOT->GetListOfCleanups()->Remove(this);
1221}
1222
1223////////////////////////////////////////////////////////////////////////////////
1224/// Show the fit panel (possible only via context menu).
1225
1227{
1228 if (!gROOT->GetListOfCleanups()->FindObject(this))
1229 gROOT->GetListOfCleanups()->Add(this);
1230
1231 if (!fgFitDialog->IsMapped()) {
1233 gVirtualX->RaiseWindow(GetId());
1234 }
1235 fParentPad = static_cast<TPad*>(pad);
1236 SetCanvas(pad->GetCanvas());
1237 SetFitObject(pad, obj, kButton1Down);
1238}
1239
1240////////////////////////////////////////////////////////////////////////////////
1241/// Close fit panel window.
1242
1244{
1245 Hide();
1246}
1247
1248//______________________________________________________________________________
1249// TFitEditor *&TFitEditor::GetFP()
1250// {
1251// // Static: return main fit panel
1252// return fgFitDialog;
1253// }
1254
1255////////////////////////////////////////////////////////////////////////////////
1256/// Called to delete the fit panel.
1257
1259{
1260 TQObject::Disconnect("TCanvas", "Closed()");
1261 delete fgFitDialog;
1262 fgFitDialog = 0;
1263}
1264
1265////////////////////////////////////////////////////////////////////////////////
1266/// Set the fit panel GUI according to the selected object.
1267
1269{
1270 if (!fFitObject) return;
1271
1272 DrawSelection(true);
1273
1274 if ( fType == kObjectTree )
1275 // Don't do anything with the sliders, as they work with TAxis
1276 // that are not defined for the TTree
1277 return;
1278
1279 // sliders
1280 if (fType != kObjectTree) { // This is as fDim > 0
1281 TH1* hist = 0;
1282 switch (fType) {
1283 case kObjectHisto:
1284 hist = (TH1*)fFitObject;
1285 break;
1286
1287 case kObjectGraph:
1288 hist = ((TGraph*)fFitObject)->GetHistogram();
1289 break;
1290
1291 case kObjectMultiGraph:
1292 hist = ((TMultiGraph*)fFitObject)->GetHistogram();
1293 break;
1294
1295 case kObjectGraph2D:
1296 hist = ((TGraph2D*)fFitObject)->GetHistogram("empty");
1297 break;
1298
1299 case kObjectHStack:
1300 hist = (TH1 *)((THStack *)fFitObject)->GetHists()->First();
1301
1302 case kObjectTree:
1303 default:
1304 break;
1305 }
1306
1307
1308 if (!hist) {
1309 Error("UpdateGUI","No hist is present - this should not happen, please report."
1310 "The FitPanel might be in an inconsistent state");
1311 //assert(hist);
1312 return;
1313 }
1314
1315 fSliderX->Disconnect("PositionChanged()");
1316 fSliderXMin->Disconnect("ValueChanged()");
1317 fSliderXMax->Disconnect("ValueChanged()");
1318
1319 if (!fSliderXParent->IsMapped())
1321
1322 fXaxis = hist->GetXaxis();
1323 fYaxis = hist->GetYaxis();
1324 fZaxis = hist->GetZaxis();
1325 Int_t ixrange = fXaxis->GetNbins();
1326 Int_t ixmin = fXaxis->GetFirst();
1327 Int_t ixmax = fXaxis->GetLast();
1328
1329 if (ixmin > 1 || ixmax < ixrange) {
1330 fSliderX->SetRange(ixmin,ixmax);
1331 fSliderX->SetPosition(ixmin, ixmax);
1332 } else {
1333 fSliderX->SetRange(1,ixrange);
1334 fSliderX->SetPosition(ixmin,ixmax);
1335 }
1336
1337 fSliderX->SetScale(5);
1338
1340 fXaxis->GetBinLowEdge( static_cast<Int_t>( fSliderX->GetMinPosition() ) ),
1341 fXaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderX->GetMaxPosition() ) ));
1344 fXaxis->GetBinLowEdge( static_cast<Int_t>( fSliderX->GetMinPosition() ) ),
1345 fXaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderX->GetMaxPosition() ) ));
1347
1348 fSliderX->Connect("PositionChanged()","TFitEditor",this, "DoSliderXMoved()");
1349 fSliderXMax->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderXChanged()");
1350 fSliderXMin->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderXChanged()");
1351 }
1352
1353 if (fDim > 1) {
1354 fSliderY->Disconnect("PositionChanged()");
1355 fSliderYMin->Disconnect("ValueChanged()");
1356 fSliderYMax->Disconnect("ValueChanged()");
1357
1358 if (!fSliderYParent->IsMapped())
1360 if (fSliderZParent->IsMapped())
1362
1363 Int_t iymin = 0, iymax = 0, iyrange = 0;
1364 switch (fType) {
1365 case kObjectHisto:
1366 case kObjectGraph2D:
1367 case kObjectHStack:
1368 iyrange = fYaxis->GetNbins();
1369 iymin = fYaxis->GetFirst();
1370 iymax = fYaxis->GetLast();
1371 break;
1372
1373 case kObjectGraph:
1374 case kObjectMultiGraph:
1375 case kObjectTree:
1376 default:
1377 //not implemented
1378 break;
1379 }
1380
1381 if (iymin > 1 || iymax < iyrange) {
1382 fSliderY->SetRange(iymin,iymax);
1383 fSliderY->SetPosition(iymin, iymax);
1384 } else {
1385 fSliderY->SetRange(1,iyrange);
1386 fSliderY->SetPosition(iymin,iymax);
1387 }
1388
1389 fSliderY->SetScale(5);
1390
1392 fYaxis->GetBinLowEdge( static_cast<Int_t>( fSliderY->GetMinPosition() ) ),
1393 fYaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderY->GetMaxPosition() ) ));
1396 fYaxis->GetBinLowEdge( static_cast<Int_t>( fSliderY->GetMinPosition() ) ),
1397 fYaxis->GetBinUpEdge ( static_cast<Int_t>( fSliderY->GetMaxPosition() ) ));
1399
1400 fSliderY->Connect("PositionChanged()","TFitEditor",this, "DoSliderYMoved()");
1401 fSliderYMax->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderYChanged()");
1402 fSliderYMin->Connect("ValueSet(Long_t)", "TFitEditor", this, "DoNumericSliderYChanged()");
1403 }
1404
1405
1406 if (fDim > 2) {
1407 fSliderZ->Disconnect("PositionChanged()");
1408
1409 if (!fSliderZParent->IsMapped())
1411
1412 Int_t izmin = 0, izmax = 0, izrange = 0;
1413 switch (fType) {
1414 case kObjectHStack:
1415 case kObjectHisto:
1416 izrange = fZaxis->GetNbins();
1417 izmin = fZaxis->GetFirst();
1418 izmax = fZaxis->GetLast();
1419 break;
1420
1421 case kObjectGraph:
1422 case kObjectGraph2D:
1423 case kObjectMultiGraph:
1424 case kObjectTree:
1425 default:
1426 //not implemented
1427 break;
1428 }
1429
1430 if (izmin > 1 || izmax < izrange) {
1431 fSliderZ->SetRange(izmin,izmax);
1432 fSliderZ->SetPosition(izmin, izmax);
1433 } else {
1434 fSliderZ->SetRange(1,izrange);
1435 fSliderZ->SetPosition(izmin,izmax);
1436 }
1437
1438 fSliderZ->SetScale(5);
1439 fSliderZ->Connect("PositionChanged()","TFitEditor",this, "DoSliderZMoved()");
1440 }
1441}
1442
1443////////////////////////////////////////////////////////////////////////////////
1444/// Slot called when the user clicks on an object inside a canvas.
1445/// Updates pointers to the parent pad and the selected object
1446/// for fitting (if suitable).
1447
1449{
1450 if (event != kButton1Down) return;
1451
1452 if ( !obj ) {
1453 DoNoSelection();
1454 return;
1455 }
1456
1457 // is obj suitable for fitting?
1458 if (!SetObjectType(obj)) return;
1459
1460 fParentPad = pad;
1461 fFitObject = obj;
1462 ShowObjectName(obj);
1463 UpdateGUI();
1464
1465 ConnectSlots();
1466
1467 TF1* fitFunc = HasFitFunction();
1468
1469 if (fitFunc)
1470 {
1471 //fFuncPars = FuncParams_t( fitFunc->GetNpar() );
1472 GetParameters(fFuncPars, fitFunc);
1473
1474 TString tmpStr = fitFunc->GetExpFormula();
1475 TGLBEntry *en = 0;
1476 // If the function comes from a C raw function.
1477 if ( tmpStr.Length() == 0 )
1478 {
1479 // Show the name of the function
1480 fEnteredFunc->SetText(fitFunc->GetName());
1481 en= fFuncList->FindEntry(fitFunc->GetName());
1482 // Don't allow edition!
1484 }
1485 // otherwise, it's got a formula
1486 else
1487 {
1488 // Show the formula
1489 fEnteredFunc->SetText(fitFunc->GetExpFormula().Data());
1490 en= fFuncList->FindEntry(fitFunc->GetExpFormula().Data());
1492 }
1493 // Select the proper entry in the function list
1494 if (en) fFuncList->Select(en->EntryId());
1495 }
1496 else
1497 { // if there is no fit function in the object
1498 // Use the selected function in fFuncList
1500 // Add the text to fEnteredFunc
1501 if (te && fNone->GetState() == kButtonDown)
1503 else if (te && fAdd->GetState() == kButtonDown)
1504 {
1505 TString tmpStr = fEnteredFunc->GetText();
1506 tmpStr += '+';
1507 tmpStr += te->GetTitle();
1508 fEnteredFunc->SetText(tmpStr);
1509 }
1510 else if (te && fNormAdd->GetState() == kButtonDown)
1511 {
1512 TString tmpStr = fEnteredFunc->GetText();
1513 tmpStr += '+';
1514 tmpStr += te -> GetTitle();
1515 fEnteredFunc -> SetText(tmpStr);
1516 }
1517 else if (te && fConv->GetState() == kButtonDown)
1518 {
1519 TString tmpStr = fEnteredFunc->GetText();
1520 tmpStr += '*';
1521 tmpStr +=te->GetTitle();
1522 fEnteredFunc->SetText(tmpStr);
1523 }
1524 else if ( !te )
1525 // If there is no space, an error message is shown:
1526 // Error in <TString::AssertElement>: out of bounds: i = -1, Length = 0
1527 // If there is no function selected, then put nothing.
1528 fEnteredFunc->SetText(" ");
1529 }
1531
1532
1533 // Update the information about the selected object.
1540 DoLinearFit();
1541}
1542
1543////////////////////////////////////////////////////////////////////////////////
1544/// Slot called when users close a TCanvas or when the user select
1545/// no object.
1546
1548{
1549 if (gROOT->GetListOfCanvases()->IsEmpty()) {
1550 Terminate();
1551 return;
1552 }
1553
1554 // Minimize user interaction until an object is selected
1556 fParentPad = 0;
1557 fFitObject = 0;
1558 fStatusBar->SetText("No selection",0);
1560 Layout();
1561
1566}
1567
1568////////////////////////////////////////////////////////////////////////////////
1569/// When obj is deleted, clear fFitObject if fFitObject = obj.
1570
1572{
1573 if (obj == fFitObject) {
1574 fFitObject = 0;
1576 fStatusBar->SetText("No selection",0);
1578 Layout();
1579
1583
1584 TQObject::Connect("TCanvas", "Selected(TVirtualPad *, TObject *, Int_t)",
1585 "TFitEditor",this,
1586 "SetFitObject(TVirtualPad *, TObject *, Int_t)");
1587 TQObject::Connect("TCanvas", "Closed()", "TFitEditor", this,
1588 "DoNoSelection()");
1589
1590 DoUpdate();
1591 return;
1592 }
1593 if (obj == fParentPad) {
1594 fFitObject = 0;
1595 fParentPad = 0;
1597 fStatusBar->SetText("No selection",0);
1599 Layout();
1600
1604 }
1605}
1606
1607////////////////////////////////////////////////////////////////////////////////
1608/// Fills the list of functions depending on the type of fit
1609/// selected.
1610
1612{
1614 // Case when the user has selected predefined functions in 1D.
1615 if ( fTypeFit->GetSelected() == kFP_PRED1D && fDim <= 1 ) {
1616 // Fill function list combo box.
1617 fFuncList->AddEntry("gaus" , kFP_GAUS);
1618 fFuncList->AddEntry("gausn", kFP_GAUSN);
1619 fFuncList->AddEntry("expo", kFP_EXPO);
1620 fFuncList->AddEntry("landau", kFP_LAND);
1621 fFuncList->AddEntry("landaun",kFP_LANDN);
1622 fFuncList->AddEntry("pol0", kFP_POL0);
1623 fFuncList->AddEntry("pol1", kFP_POL1);
1624 fFuncList->AddEntry("pol2", kFP_POL2);
1625 fFuncList->AddEntry("pol3", kFP_POL3);
1626 fFuncList->AddEntry("pol4", kFP_POL4);
1627 fFuncList->AddEntry("pol5", kFP_POL5);
1628 fFuncList->AddEntry("pol6", kFP_POL6);
1629 fFuncList->AddEntry("pol7", kFP_POL7);
1630 fFuncList->AddEntry("pol8", kFP_POL8);
1631 fFuncList->AddEntry("pol9", kFP_POL9);
1632 fFuncList->AddEntry("cheb0", kFP_CHEB0);
1633 fFuncList->AddEntry("cheb1", kFP_CHEB1);
1634 fFuncList->AddEntry("cheb2", kFP_CHEB2);
1635 fFuncList->AddEntry("cheb3", kFP_CHEB3);
1636 fFuncList->AddEntry("cheb4", kFP_CHEB4);
1637 fFuncList->AddEntry("cheb5", kFP_CHEB5);
1638 fFuncList->AddEntry("cheb6", kFP_CHEB6);
1639 fFuncList->AddEntry("cheb7", kFP_CHEB7);
1640 fFuncList->AddEntry("cheb8", kFP_CHEB8);
1641 fFuncList->AddEntry("cheb9", kFP_CHEB9);
1642 fFuncList->AddEntry("user", kFP_USER);
1643
1644 // Need to be setted this way, otherwise when the functions
1645 // are removed, the list doesn't show them.
1647 lb->Resize(lb->GetWidth(), 200);
1648
1649 // Select Gaus1D by default
1651
1652 }
1653 // Case for predefined 2D functions
1654 else if ( fTypeFit->GetSelected() == kFP_PRED2D && fDim == 2 ) {
1655 fFuncList->AddEntry("xygaus", kFP_XYGAUS);
1656 fFuncList->AddEntry("bigaus", kFP_BIGAUS);
1657 fFuncList->AddEntry("xyexpo", kFP_XYEXP);
1658 fFuncList->AddEntry("xylandau", kFP_XYLAN);
1659 fFuncList->AddEntry("xylandaun", kFP_XYLANN);
1660
1661 // Need to be setted this way, otherwise when the functions
1662 // are removed, the list doesn't show them.x
1664 lb->Resize(lb->GetWidth(), 200);
1665
1666 // Select Gaus2D by default
1668 }
1669 // Case for user defined functions. References to these functions
1670 // are kept by the fitpanel, so the information is gathered from
1671 // there.
1672 else if ( fTypeFit->GetSelected() == kFP_UFUNC ) {
1673 Int_t newid = kFP_ALTFUNC;
1674
1675 // Add system functions
1676 for (auto f : fSystemFuncs) {
1677 // Don't include system functions that has been previously
1678 // used to fit, as those are included under the kFP_PREVFIT
1679 // section.
1680 if ( strncmp(f->GetName(), "PrevFit", 7) != 0 ) {
1681 // If the dimension of the object coincides with the
1682 // dimension of the function, then include the function in
1683 // the list. It will also include de function if the
1684 // dimension of the object is 0 (i.e. a multivariable
1685 // TTree) as it is currently imposible to know how many
1686 // dimensions a TF1 coming from a C raw function has.
1687 if ( f->GetNdim() == fDim || fDim == 0) {
1688 fFuncList->AddEntry(f->GetName(), newid++);
1689 }
1690 }
1691 }
1692
1693 // If no function was added
1694 if ( newid != kFP_ALTFUNC )
1695 fFuncList->Select(newid-1);
1696 else if( fDim == 1 ) {
1697 // Select predefined 1D functions for 1D objects
1699 } else if( fDim == 2 ) {
1700 // Select predefined 2D functions for 2D objects
1702 }
1703 }
1704 // Case for previously used functions.
1705 else if ( fTypeFit->GetSelected() == kFP_PREVFIT ) {
1706 Int_t newid = kFP_ALTFUNC;
1707
1708 // Look only for those functions used in the selected object
1709 std::pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(fFitObject);
1710 // Then go over all those functions and add them to the list
1711 for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
1712 fFuncList->AddEntry(it->second->GetName(), newid++);
1713 }
1714
1715 // If no functions were added.
1716 if ( newid == kFP_ALTFUNC ) {
1717 // Remove the entry previous fit from fTypeFit
1719 if( fDim == 1 )
1720 // Select predefined 1D functions for 1D objects
1722 else if ( fDim == 2 )
1723 // Select predefined 2D functions for 2D objects
1725 else
1726 // For more than 2 dimensions, select the user functions.
1728 }
1729 else
1730 // If there is there are previously used functions, select
1731 // the last one inserted.
1732 fFuncList->Select(newid-1, kTRUE);
1733 }
1734}
1735
1736////////////////////////////////////////////////////////////////////////////////
1737/// Fills the list of methods depending on the minimization library
1738/// selected.
1739
1741{
1743
1744 if ( fLibMinuit->GetState() == kButtonDown )
1745 {
1746 fMinMethodList->AddEntry("MIGRAD" , kFP_MIGRAD);
1747 fMinMethodList->AddEntry("SIMPLEX" , kFP_SIMPLX);
1748 fMinMethodList->AddEntry("SCAN" , kFP_SCAN);
1749 fMinMethodList->AddEntry("Combination" , kFP_COMBINATION);
1751 fStatusBar->SetText("MIGRAD",2);
1752 } else if ( fLibFumili->GetState() == kButtonDown )
1753 {
1754 fMinMethodList->AddEntry("FUMILI" , kFP_FUMILI);
1756 fStatusBar->SetText("FUMILI",2);
1757 } else if ( fLibGSL->GetState() == kButtonDown )
1758 {
1759 fMinMethodList->AddEntry("Fletcher-Reeves conjugate gradient" , kFP_GSLFR);
1760 fMinMethodList->AddEntry("Polak-Ribiere conjugate gradient" , kFP_GSLPR);
1761 fMinMethodList->AddEntry("BFGS conjugate gradient" , kFP_BFGS);
1762 fMinMethodList->AddEntry("BFGS conjugate gradient (Version 2)", kFP_BFGS2);
1763 fMinMethodList->AddEntry("Levenberg-Marquardt" , kFP_GSLLM);
1764 fMinMethodList->AddEntry("Simulated Annealing" , kFP_GSLSA);
1766 fStatusBar->SetText("CONJFR",2);
1767 } else if ( fLibGenetics->GetState() == kButtonDown )
1768 {
1769 if ( gPluginMgr->FindHandler("ROOT::Math::Minimizer","GAlibMin") ) {
1770 fMinMethodList->AddEntry("GA Lib Genetic Algorithm" , kFP_GALIB);
1772 } else if (gPluginMgr->FindHandler("ROOT::Math::Minimizer","Genetic")) {
1773 fMinMethodList->AddEntry("TMVA Genetic Algorithm" , kFP_TMVAGA);
1775 }
1776 } else // if ( fLibMinuit2->GetState() == kButtonDown )
1777 {
1778 fMinMethodList->AddEntry("MIGRAD" , kFP_MIGRAD);
1779 fMinMethodList->AddEntry("SIMPLEX" , kFP_SIMPLX);
1780 fMinMethodList->AddEntry("FUMILI" , kFP_FUMILI);
1781 fMinMethodList->AddEntry("SCAN" , kFP_SCAN);
1782 fMinMethodList->AddEntry("Combination" , kFP_COMBINATION);
1784 fStatusBar->SetText("MIGRAD",2);
1785 }
1786}
1787
1788void SearchCanvases(TSeqCollection* canvases, std::vector<TObject*>& objects)
1789{
1790 // Auxiliary function to recursively search for objects inside the
1791 // current canvases.
1792
1793 TIter canvasIter(canvases);
1794 // Iterate over all the canvases in canvases.
1795 while(TObject* obj = (TObject*) canvasIter()) {
1796 // If the object is another canvas, call this function
1797 // recursively.
1798 if ( TPad* can = dynamic_cast<TPad*>(obj))
1799 SearchCanvases(can->GetListOfPrimitives(), objects);
1800 // Otherwhise, if it's a recognised object, add it to the vector
1801 else if ( dynamic_cast<TH1*>(obj)
1802 || dynamic_cast<TGraph*>(obj)
1803 || dynamic_cast<TGraph2D*>(obj)
1804 || dynamic_cast<TMultiGraph*>(obj)
1805 || dynamic_cast<THStack*>(obj)
1806 || dynamic_cast<TTree*>(obj) ) {
1807 bool insertNew = true;
1808 // Be careful no to insert the same element twice.
1809 for ( std::vector<TObject*>::iterator i = objects.begin(); i != objects.end(); ++i )
1810 if ( (*i) == obj ) {
1811 insertNew = false;
1812 break;
1813 }
1814 // If the object is not already in the vector, then insert
1815 // it.
1816 if ( insertNew ) objects.push_back(obj);
1817 }
1818 }
1819}
1820
1821////////////////////////////////////////////////////////////////////////////////
1822/// Create a combo box with all the possible objects to be fitted.
1823
1825{
1826 // Get the title of the entry selected, so that we can select it
1827 // again once the fDataSet has been refilled.
1829 TString selEntryStr;
1830 if ( entry ) {
1831 selEntryStr = entry->GetTitle();
1832 }
1833
1834 // Remove all the elements
1836 std::vector<TObject*> objects;
1837
1838 // Get all the objects registered in gDirectory
1839 if (gDirectory) {
1840 TList * l = gDirectory->GetList();
1841 if (l) {
1842 TIter next(l);
1843 TObject* obj = NULL;
1844 while ( (obj = (TObject*) next()) ) {
1845 // But only if they are of a type recognized by the FitPanel
1846 if ( dynamic_cast<TH1*>(obj) ||
1847 dynamic_cast<TGraph2D*>(obj) ||
1848 dynamic_cast<TTree*>(obj) ) {
1849 objects.push_back(obj);
1850 }
1851 }
1852 }
1853 }
1854
1855 // Look for all the drawn objects. The method will take care the
1856 // same objects are not inserted twice.
1857 SearchCanvases(gROOT->GetListOfCanvases(), objects);
1858
1859 // Add all the objects stored in the vector
1860 int selected = kFP_NOSEL;
1861 // Add the No selection.
1862 Int_t newid = kFP_NOSEL;
1863 fDataSet->AddEntry("No Selection", newid++);
1864 for ( std::vector<TObject*>::iterator i = objects.begin(); i != objects.end(); ++i ) {
1865 // Insert the name as the class name followed by the name of the
1866 // object.
1867 TString name = (*i)->ClassName(); name.Append("::"); name.Append((*i)->GetName());
1868 // Check whether the names are the same!
1869 if ( selEntryStr && name == selEntryStr )
1870 selected = newid;
1871 fDataSet->AddEntry(name, newid++);
1872 }
1873
1874 // If there was an entry selected (which should be always the case
1875 // except the first time this method is executed), then make it the
1876 // selected one again.
1877 if (entry) {
1878 fDataSet->Select(selected);
1879 }
1880}
1881
1882////////////////////////////////////////////////////////////////////////////////
1883/// Create method list in a combo box.
1884
1886{
1887 TGComboBox *c = new TGComboBox(parent, id);
1888 c->AddEntry("Chi-square", kFP_MCHIS);
1889 c->AddEntry("Binned Likelihood", kFP_MBINL);
1890 c->AddEntry("Unbinned Likelihood", kFP_MUBIN);
1891 //c->AddEntry("User", kFP_MUSER); //for later use
1892 c->Select(kFP_MCHIS);
1893 return c;
1894}
1895
1896////////////////////////////////////////////////////////////////////////////////
1897/// Slot connected to advanced option button (opens a dialog).
1898
1900{
1902}
1903
1904////////////////////////////////////////////////////////////////////////////////
1905/// Slot connected to 'include emtry bins and forse all weights to 1' setting.
1906
1908{
1912}
1913
1914////////////////////////////////////////////////////////////////////////////////
1915
1917{
1918 if ( fUseRange->GetState() == kButtonDown ) {
1920 // Get the function
1921 TF1* tmpTF1 = FindFunction();
1922 if ( !tmpTF1 ) {
1925 tmpTF1 = (TF1*) GetFitObjectListOfFunctions()->FindObject( te->GetTitle() );
1926 }
1927 }
1928 // If the function has been retrieved, i.e. is a registered function.
1929 if ( tmpTF1 ) {
1930 Double_t xmin, ymin, zmin, xmax, ymax, zmax;
1931 // Get the range
1932 tmpTF1->GetRange(xmin, ymin, zmin, xmax, ymax, zmax);
1933 // And set the sliders
1934 if ( fType != kObjectTree ) {
1938 if ( fDim > 1 ) {
1942 }
1943 }
1944 }
1945 }
1947 }
1948}
1949
1950////////////////////////////////////////////////////////////////////////////////
1951/// Slot connected to 'set all weights to 1' setting.
1952
1954{
1958}
1959
1960////////////////////////////////////////////////////////////////////////////////
1961/// Close the fit panel.
1962
1964{
1965 Hide();
1966}
1967
1968////////////////////////////////////////////////////////////////////////////////
1969/// Easy here!
1970
1972{
1975}
1976
1977////////////////////////////////////////////////////////////////////////////////
1978/// Perform a fit with current parameters' settings.
1979
1981{
1982 if (!fFitObject) return;
1983 //if (!fParentPad) return;
1984
1985 // If fNone->GetState() == kButtonDisabled means the function is
1986 // not editable, i.e. it comes from a raw C function. So in this
1987 // case, it is editable and we have to check wheather the formula
1988 // is well built.
1990 {
1991 // If not, then show an error message and leave.
1993 "Error...", "2) Verify the entered function string!",
1994 kMBIconStop,kMBOk, 0);
1995 return;
1996 }
1997
1998 // Set the button so that the user cannot use it while fitting, set
1999 // the mouse to watch type and so on.
2001 if (gPad && gPad->GetVirtCanvas()) gPad->GetVirtCanvas()->SetCursor(kWatch);
2002 gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kWatch));
2003
2004 TVirtualPad *save = nullptr;
2005 if ( fParentPad ) {
2006 fParentPad->Disconnect("RangeAxisChanged()");
2007 save = gPad;
2008 gPad = fParentPad;
2009 fParentPad->cd();
2010
2011 if (fParentPad->GetCanvas())
2013 }
2014
2015 // Get the ranges from the sliders
2016 ROOT::Fit::DataRange drange;
2017 GetRanges(drange);
2018
2019 // Create a static pointer to fitFunc. Every second call to the
2020 // DoFit method, the old fitFunc is deleted. We need not to delete
2021 // the function after the fitting in case we want to do Advaced
2022 // graphics. The VirtualFitter need the function to be alived. One
2023 // problem, after the last fit the function is never deleted, but
2024 // ROOT's garbage collector will do the job for us.
2025 static TF1 *fitFunc = nullptr;
2026 if ( fitFunc ) {
2027 //std::cout << "TFitEditor::DoFit - deleting fit function " << fitFunc->GetName() << " " << fitFunc << std::endl;
2028 delete fitFunc;
2029 }
2030 fitFunc = GetFitFunction();
2031
2032 std::cout << "TFitEditor::DoFit - using function " << fitFunc->GetName() << " " << fitFunc << std::endl;
2033 // This assert
2034 if (!fitFunc) {
2035 Error("DoFit","This should have never happend, the fitfunc pointer is NULL! - Please Report" );
2036 return;
2037 }
2038
2039 // set parameters from panel in function
2040 SetParameters(fFuncPars, fitFunc);
2041 // Get the options stored in the GUI elements.
2043 Foption_t fitOpts;
2044 TString strDrawOpts;
2045 RetrieveOptions(fitOpts, strDrawOpts, mopts, fitFunc->GetNpar());
2046
2047 // Call the fit method, depending on the object to fit.
2048 switch (fType) {
2049 case kObjectHisto: {
2050
2051 TH1 *hist = dynamic_cast<TH1*>(fFitObject);
2052 if (hist)
2053 ROOT::Fit::FitObject(hist, fitFunc, fitOpts, mopts, strDrawOpts, drange);
2054
2055 break;
2056 }
2057 case kObjectGraph: {
2058
2059 TGraph *gr = dynamic_cast<TGraph*>(fFitObject);
2060 if (gr)
2061 FitObject(gr, fitFunc, fitOpts, mopts, strDrawOpts, drange);
2062 break;
2063 }
2064 case kObjectMultiGraph: {
2065
2066 TMultiGraph *mg = dynamic_cast<TMultiGraph*>(fFitObject);
2067 if (mg)
2068 FitObject(mg, fitFunc, fitOpts, mopts, strDrawOpts, drange);
2069
2070 break;
2071 }
2072 case kObjectGraph2D: {
2073
2074 TGraph2D *g2d = dynamic_cast<TGraph2D*>(fFitObject);
2075 if (g2d)
2076 FitObject(g2d, fitFunc, fitOpts, mopts, strDrawOpts, drange);
2077
2078 break;
2079 }
2080 case kObjectHStack: {
2081 // N/A
2082 break;
2083 }
2084 case kObjectTree: {
2085 // The three is a much more special case. The steps for
2086 // fitting have to be done manually here until they are
2087 // properly implemented within a FitObject method in
2088 // THFitImpl.cxx
2089
2090 // Retrieve the variables and cuts selected from the current
2091 // tree.
2093 TString cuts;
2095
2096 // This should be straight forward and the return should
2097 // never be called.
2098 TTree *tree = dynamic_cast<TTree*>(fFitObject);
2099 if ( !tree ) return;
2100
2101 // These method calls are just to set up everything for the
2102 // fitting. It's taken from another script.
2103 gROOT->ls();
2104 tree->Draw(variables,cuts,"goff");
2105
2106 auto player = tree->GetPlayer();
2107 if ( !player ) {
2108 Error("DoFit","Player reference is NULL");
2109 return;
2110 }
2111
2112 auto selector = dynamic_cast<TSelectorDraw *>(player->GetSelector());
2113 if ( !selector ) {
2114 Error("DoFit","Selector reference is NULL");
2115 return;
2116 }
2117
2118 // use pointer stored in the tree (not copy the data in)
2119 unsigned int ndim = player->GetDimension();
2120 if ( ndim == 0 ) {
2121 Error("DoFit","NDIM == 0");
2122 return;
2123 }
2124
2125 std::vector<double *> vlist;
2126 for (unsigned int i = 0; i < ndim; ++i) {
2127 double * v = selector->GetVal(i);
2128 if (v != 0) vlist.push_back(v);
2129 else
2130 std::cerr << "pointer for variable " << i << " is zero" << std::endl;
2131 }
2132 if (vlist.size() != ndim) {
2133 Error("DoFit","Vector is not complete");
2134 return;
2135 }
2136
2137 // fill the data
2138 Long64_t nrows = player->GetSelectedRows();
2139 if ( !nrows ) {
2140 Error("DoFit","NROWS == 0");
2141 return;
2142 }
2143
2144 ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
2145
2146 for ( int i = 0; i < std::min(int(fitdata->Size()),10); ++i) {
2147 // print j coordinate
2148 for (unsigned int j = 0; j < ndim; ++j) {
2149 printf(" x_%d [%d] = %f \n", j, i,*(fitdata->Coords(i)+j) );
2150 }
2151 printf("\n");
2152 }
2153
2154
2155 //TVirtualFitter::SetDefaultFitter("Minuit");
2156 Foption_t fitOption;
2158 fitOption.Verbose=1;
2159
2160 // After all the set up is performed, then do the Fit!!
2161 ROOT::Fit::UnBinFit(fitdata, fitFunc, fitOption, minOption);
2162
2163 break;
2164 }
2165 }
2166
2167 // if SAME is set re-plot the function
2168 // useful in case histogram was drawn with HIST
2169 // and no function will be drawm)
2170 if (fDrawSame->GetState() == kButtonDown && fitFunc)
2171 fitFunc->Draw("same");
2172
2173
2174 // update parameters value shown in dialog
2175 //if (!fFuncPars) fFuncPars = new Double_t[fitFunc->GetNpar()][3];
2176 GetParameters(fFuncPars,fitFunc);
2177
2178 // Save fit data for future use as a PrevFit function.
2179 TF1* tmpTF1 = copyTF1(fitFunc);
2180 TString name = TString::Format("PrevFit-%d", (int) fPrevFit.size() + 1);
2181 if (!strstr(fitFunc->GetName(),"PrevFit"))
2182 name.Append(TString::Format("-%s", fitFunc->GetName()));
2183 tmpTF1->SetName(name.Data());
2184 fPrevFit.emplace(fFitObject, tmpTF1);
2185 fSystemFuncs.emplace_back( copyTF1(tmpTF1) );
2186
2187 float xmin = 0.f, xmax = 0.f, ymin = 0.f, ymax = 0.f, zmin = 0.f, zmax = 0.f;
2188 if ( fParentPad ) {
2190 // As the range is not changed, save the old values and restore
2191 // after the GUI has been updated. It would be more elegant to
2192 // disconnect the signal from fParentPad, however, this doesn't
2193 // work for unknown reasons.
2195 if ( fDim > 1 ) fSliderY->GetPosition(ymin, ymax);
2196 if ( fDim > 2 ) fSliderZ->GetPosition(zmin, zmax);
2197 fParentPad->Update();
2198 }
2199
2200 // In case the fit method draws something! Set the canvas!
2201 fParentPad = gPad;
2202 UpdateGUI();
2203
2204 // Change the sliders if necessary.
2205 if ( fParentPad ) {
2207 if ( fType != kObjectTree && fDim > 1 ) { fSliderY->SetPosition(ymin, ymax); DoSliderYMoved(); }
2208 if ( fType != kObjectTree && fDim > 2 ) { fSliderZ->SetPosition(zmin, zmax); DoSliderZMoved(); }
2209 if (fParentPad->GetCanvas())
2211 fParentPad->Connect("RangeAxisChanged()", "TFitEditor", this, "UpdateGUI()");
2212
2213 if (save) gPad = save;
2217 }
2218
2219 // Restore the Fit button and mouse cursor to their proper state.
2220 if (gPad && gPad->GetVirtCanvas()) gPad->GetVirtCanvas()->SetCursor(kPointer);
2221 gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
2223
2224 if ( !fTypeFit->FindEntry("Prev. Fit") )
2226
2228}
2229
2230////////////////////////////////////////////////////////////////////////////////
2231/// Check entered function string.
2232
2234{
2235 Int_t rvalue = 0;
2236 if ( fDim == 1 || fDim == 0 ) {
2237 TF1 form("tmpCheck", fname);
2238 // coverity[uninit_use_in_call]
2239 rvalue = form.IsValid() ? 0 : -1;
2240 } else if ( fDim == 2 ) {
2241 TF2 form("tmpCheck", fname);
2242 // coverity[uninit_use_in_call]
2243 rvalue = form.IsValid() ? 0 : -1;
2244 } else if ( fDim == 3 ) {
2245 TF3 form("tmpCheck", fname);
2246 // coverity[uninit_use_in_call]
2247 rvalue = form.IsValid() ? 0 : -1;
2248 }
2249
2250 return rvalue;
2251}
2252
2253////////////////////////////////////////////////////////////////////////////////
2254/// Slot connected to addition of predefined functions. It will
2255/// insert the next selected function with a plus sign so that it
2256/// doesn't override the current content of the formula.
2257
2259{
2260 static Bool_t first = kFALSE;
2262 if (on) {
2263 if (!first) {
2264 fSelLabel->SetText(s.Sizeof()>30?s(0,30)+"...":s);
2265 s += "(0)";
2266 fEnteredFunc->SetText(s.Data());
2267 first = kTRUE;
2269 }
2270 } else {
2271 first = kFALSE;
2272 }
2273}
2274////////////////////////////////////////////////////////////////////////////////
2275/// Slot connected to addition of predefined functions. It will
2276/// insert the next selected function with a plus sign so that it
2277/// doesn't override the current content of the formula.
2278
2280{
2281 /*
2282 static Bool_t first = kFALSE;
2283 TString s = fEnteredFunc->GetText();
2284 if (on) {
2285 if (!first) {
2286 fSelLabel->SetText(s.Sizeof()>30?s(0,30)+"...":s);
2287 fEnteredFunc->SetText(s.Data());
2288 first = kTRUE;
2289 ((TGCompositeFrame *)fSelLabel->GetParent())->Layout();
2290 }
2291 } else {
2292 first = kFALSE;
2293 }*/
2294
2295 if (on) Info("DoNormAddition","Normalized addition is selected");
2296}
2297
2298////////////////////////////////////////////////////////////////////////////////
2299/// Slot connected to addition of predefined functions. It will
2300/// insert the next selected function with a plus sign so that it
2301/// doesn't override the current content of the formula.
2302
2304{
2305 /*
2306 static Bool_t first = kFALSE;
2307 TString s = fEnteredFunc->GetText();
2308 if (on) {
2309 if (!first) {
2310 fSelLabel->SetText(s.Sizeof()>30?s(0,30)+"...":s);
2311 // s += "(0)";
2312 fEnteredFunc->SetText(s.Data());
2313 first = kTRUE;
2314 ((TGCompositeFrame *)fSelLabel->GetParent())->Layout();
2315 }
2316 } else
2317 first = kFALSE;*/
2318
2319 if (on) Info("DoConvolution","Convolution is selected");
2320}
2321
2322////////////////////////////////////////////////////////////////////////////////
2323/// Selects the data set to be fitted
2324
2326{
2327 if ( selected == kFP_NOSEL ) {
2328 DoNoSelection();
2329 return;
2330 }
2331
2332 // Get the name and class of the selected object.
2333 TGTextLBEntry* textEntry = static_cast<TGTextLBEntry*>(fDataSet->GetListBox()->GetEntry(selected));
2334 if (!textEntry) return;
2335 TString textEntryStr = textEntry->GetText()->GetString();
2336 TString name = textEntry->GetText()->GetString()+textEntry->GetText()->First(':')+2;
2337 TString className = textEntryStr(0,textEntry->GetText()->First(':'));
2338
2339 // Check the object exists in the ROOT session and it is registered
2340 TObject* objSelected(0);
2341 if ( className == "TTree" ) {
2342 // It's a tree, so the name is before the space (' ')
2343 TString lookStr;
2344 if ( name.First(' ') == kNPOS )
2345 lookStr = name;
2346 else
2347 lookStr = name(0, name.First(' '));
2348 //std::cout << "\t1 SITREE: '" << lookStr << "'" << std::endl;
2349 objSelected = gROOT->FindObject(lookStr);
2350 } else {
2351 // It's not a tree, so the name is the complete string
2352 //std::cout << "\t1 NOTREE: '" << name << "'" << std::endl;
2353 objSelected = gROOT->FindObject(name);
2354 }
2355 if ( !objSelected )
2356 {
2357 //std::cerr << "Object not found! Please report the error! " << std::endl;
2358 return;
2359 }
2360
2361 // If it is a tree, and there are no variables selected, show a dialog
2362 if ( objSelected->InheritsFrom(TTree::Class()) &&
2363 name.First(' ') == kNPOS ) {
2364 char variables[256] = {0}; char cuts[256] = {0};
2365 strlcpy(variables, "Sin input!", 256);
2366 new TTreeInput( fClient->GetRoot(), GetMainFrame(), variables, cuts );
2367 if ( strcmp ( variables, "" ) == 0 ) {
2368 DoNoSelection();
2369 return;
2370 }
2371 ProcessTreeInput(objSelected, selected, variables, cuts);
2372 }
2373
2374 // Search the canvas where the object is drawn, if any
2375 TPad* currentPad = NULL;
2376 bool found = false;
2377 std::queue<TPad*> stPad;
2378 TIter padIter( gROOT->GetListOfCanvases() );
2379 while ( TObject* canvas = static_cast<TObject*>(padIter() ) ) {
2380 if ( dynamic_cast<TPad*>(canvas) )
2381 stPad.push(dynamic_cast<TPad*>(canvas));
2382 }
2383
2384 while ( !stPad.empty() && !found ) {
2385 currentPad = stPad.front();
2386 stPad.pop();
2387 TIter elemIter( currentPad->GetListOfPrimitives() );
2388 while ( TObject* elem = static_cast<TObject*>(elemIter() ) ) {
2389 if ( elem == objSelected ) {
2390 found = true;
2391 break;
2392 } else if ( dynamic_cast<TPad*>(elem) )
2393 stPad.push( dynamic_cast<TPad*>(elem) );
2394 }
2395 }
2396
2397 // Set the proper object and canvas (if found!)
2398 SetFitObject( found ? currentPad : nullptr, objSelected, kButton1Down);
2399}
2400
2402{
2403 // If the input is valid, insert the tree with the selections as an entry to fDataSet
2404 TString entryName = (objSelected)->ClassName(); entryName.Append("::"); entryName.Append((objSelected)->GetName());
2405 entryName.Append(" (\""); entryName.Append(variables); entryName.Append("\", \"");
2406 entryName.Append(cuts); entryName.Append("\")");
2408 fDataSet->InsertEntry(entryName, newid, selected );
2409 fDataSet->Select(newid);
2410}
2411
2412////////////////////////////////////////////////////////////////////////////////
2413/// Slot connected to predefined fit function settings.
2414
2416{
2418
2419 // check that selected passesd value is the correct one in the TextEntry
2420 R__ASSERT( selected == te->EntryId());
2421 //std::cout << "calling do function " << selected << " " << te->GetTitle() << " function " << te->EntryId() << std::endl;
2422 //selected = te->EntryId();
2423
2424 bool editable = false;
2426 {
2427 // Get the function selected and check weather it is a raw C
2428 // function or not
2429 TF1* tmpTF1 = FindFunction();
2430 if ( !tmpTF1 )
2431 {
2433 tmpTF1 = (TF1*) GetFitObjectListOfFunctions()->FindObject( te->GetTitle() );
2434 }
2435 if ( tmpTF1 && strcmp(tmpTF1->GetExpFormula(), "") )
2436 {
2437 editable = kTRUE;
2439 }
2440 else
2441 {
2442 if ( selected <= kFP_USER )
2443 editable = kTRUE;
2444 else
2445 editable = kFALSE;
2447 }
2448 // Once you have the function, set the editable.
2449 SetEditable(editable);
2450 }
2451 else if (fAdd -> GetState() == kButtonDown)
2452 {
2453 // If the add button is down don't replace the fEnteredFunc text
2454 Int_t np = 0;
2455 TString s = "";
2456 if (!strcmp(fEnteredFunc->GetText(), ""))
2457 {
2459 }
2460 else
2461 {
2462 s = fEnteredFunc->GetTitle();
2463 TFormula tmp("tmp", fEnteredFunc->GetText());
2464 np = tmp.GetNpar();
2465 }
2466 if (np)
2467 s += TString::Format("+%s(%d)", te->GetTitle(), np);
2468 else
2469 s += TString::Format("%s(%d)", te->GetTitle(), np);
2470 fEnteredFunc->SetText(s.Data());
2471 editable = true;
2472 }
2473 else if (fNormAdd->GetState() == kButtonDown)
2474 {
2475 // If the normadd button is down don't replace the fEnteredFunc text
2476 Int_t np = 0;
2477 TString s = "";
2478 if (!strcmp(fEnteredFunc->GetText(), ""))
2479 {
2481 }
2482 else
2483 {
2484 s = fEnteredFunc->GetTitle();
2485 TFormula tmp("tmp", fEnteredFunc->GetText());
2486 np = tmp.GetNpar();
2487 }
2488 if (np)
2489 s += TString::Format("+%s", te->GetTitle());
2490 else
2491 s += TString::Format("%s", te->GetTitle());
2492 fEnteredFunc->SetText(s.Data());
2493 //std::cout <<fEnteredFunc->GetText()<<std::endl;
2494 editable = true;
2495 }
2496 else if (fConv->GetState() == kButtonDown)
2497 {
2498 // If the normadd button is down don't replace the fEnteredFunc text
2499 Int_t np = 0;
2500 TString s = "";
2501 if (!strcmp(fEnteredFunc->GetText(), ""))
2503 else
2504 {
2505 s = fEnteredFunc->GetTitle();
2506 TFormula tmp("tmp", fEnteredFunc->GetText());
2507 np = tmp.GetNpar();
2508 }
2509 if (np)
2510 s += TString::Format("*%s", te->GetTitle());
2511 else
2512 s += TString::Format("%s", te->GetTitle());
2513 fEnteredFunc->SetText(s.Data());
2514 //std::cout <<fEnteredFunc->GetText()<<std::endl;
2515 editable = true;
2516 }
2517
2518
2519 // Get the final name in fEnteredFunc to process the function that
2520 // it would create
2521 TString tmpStr = fEnteredFunc->GetText();
2522
2523 // create TF1 with the passed string. Delete previous one if existing
2524 if (tmpStr.Contains("pol") || tmpStr.Contains("++")) {
2526 } else {
2528 }
2529
2531 fSelLabel->SetText(tmpStr.Sizeof()>30?tmpStr(0,30)+"...":tmpStr);
2533
2534 // reset function parameters if the number of parameters of the new
2535 // function is different from the old one!
2536 TF1* fitFunc = GetFitFunction();
2537 //std::cout << "TFitEditor::DoFunction - using function " << fitFunc->GetName() << " " << fitFunc << std::endl;
2538
2539 if ( fitFunc && (unsigned int) fitFunc->GetNpar() != fFuncPars.size() )
2540 fFuncPars.clear();
2541 if ( fitFunc ) {
2542 //std::cout << "TFitEditor::DoFunction - deleting function " << fitFunc->GetName() << " " << fitFunc << std::endl;
2543 delete fitFunc;
2544 }
2545}
2546
2547////////////////////////////////////////////////////////////////////////////////
2548/// Slot connected to entered function in text entry.
2549
2551{
2552 if (!strcmp(fEnteredFunc->GetText(), "")) return;
2553
2554 // Check if the function is well built
2556
2557 if (ok != 0) {
2559 "Error...", "3) Verify the entered function string!",
2560 kMBIconStop,kMBOk, 0);
2561 return;
2562 }
2563
2564 // And set the label with the entered text if everything is fine.
2566 fSelLabel->SetText(s.Sizeof()>30?s(0,30)+"...":s);
2568}
2569
2570////////////////////////////////////////////////////////////////////////////////
2571/// Slot connected to linear fit settings.
2572
2574{
2575 if (fLinearFit->GetState() == kButtonDown) {
2576 //fSetParam->SetState(kButtonDisabled);
2580 //fNoChi2->SetState(kButtonUp);
2581 } else {
2582 //fSetParam->SetState(kButtonUp);
2587 //fNoChi2->SetState(kButtonDisabled);
2588 }
2589}
2590
2591////////////////////////////////////////////////////////////////////////////////
2592/// Slot connected to 'no chi2' option settings.
2593
2595{
2596 //LM: no need to do operations here
2597 // if (fLinearFit->GetState() == kButtonUp)
2598 // fLinearFit->SetState(kButtonDown, kTRUE);
2599}
2600////////////////////////////////////////////////////////////////////////////////
2601/// Slot connected to 'robust fitting' option settings.
2602
2604{
2607 else
2609}
2610
2611////////////////////////////////////////////////////////////////////////////////
2612/// Slot connected to 'no storing, no drawing' settings.
2613
2615{
2616 if (fNoDrawing->GetState() == kButtonUp)
2618}
2619
2620////////////////////////////////////////////////////////////////////////////////
2621/// Slot connected to print option settings.
2622
2624{
2625 // Change the states of the buttons depending of which one is
2626 // selected.
2627 TGButton *btn = (TGButton *) gTQSender;
2628 Int_t id = btn->WidgetId();
2629 switch (id) {
2630 case kFP_PDEF:
2631 if (on) {
2635 }
2636 fStatusBar->SetText("Prn: DEF",4);
2637 break;
2638 case kFP_PVER:
2639 if (on) {
2643 }
2644 fStatusBar->SetText("Prn: VER",4);
2645 break;
2646 case kFP_PQET:
2647 if (on) {
2651 }
2652 fStatusBar->SetText("Prn: QT",4);
2653 default:
2654 break;
2655 }
2656}
2657
2658////////////////////////////////////////////////////////////////////////////////
2659/// Reset all fit parameters.
2660
2662{
2663 if ( fParentPad ) {
2665 fParentPad->Update();
2666 }
2667 fEnteredFunc->SetText("gaus");
2668
2669 // To restore temporary points and sliders
2670 UpdateGUI();
2671
2676 if (fUseRange->GetState() == kButtonDown)
2690 // if (fNoChi2->GetState() == kButtonDown)
2691 // fNoChi2->SetState(kButtonUp, kFALSE);
2692 if (fDrawSame->GetState() == kButtonDown)
2699 fFuncList->Select(1, kTRUE);
2700
2701 // minimization tab
2710 }
2714 }
2718 }
2719}
2720
2721////////////////////////////////////////////////////////////////////////////////
2722/// Open set parameters dialog.
2723
2725{
2726 // Get the function.
2727 TF1* fitFunc = GetFitFunction();
2728 //std::cout << "TFitEditor::DoSetParameters - using function " << fitFunc->GetName() << " " << fitFunc << std::endl;
2729
2730 if (!fitFunc) { Error("DoSetParameters","NUll function"); return; }
2731
2732 // case of special functions (gaus, expo, etc...) if the function
2733 // has not defined the parameters yet. For those, don't let the
2734 // parameters to be all equal to 0, as we can provide some good
2735 // starting value.
2736 if (fFuncPars.size() == 0) {
2737 switch (fType) {
2738 case kObjectHisto:
2739 InitParameters( fitFunc, (TH1*)fFitObject) ;
2740 break;
2741 case kObjectGraph:
2742 InitParameters( fitFunc, ((TGraph*)fFitObject));
2743 break;
2744 case kObjectMultiGraph:
2745 InitParameters( fitFunc, ((TMultiGraph*)fFitObject));
2746 break;
2747 case kObjectGraph2D:
2748 InitParameters( fitFunc, ((TGraph2D*)fFitObject));
2749 break;
2750 case kObjectHStack:
2751 case kObjectTree:
2752 default:
2753 break;
2754 }
2755 // The put these parameters into the fFuncPars structure
2756 GetParameters(fFuncPars, fitFunc);
2757 }
2758 else {
2759 // Otherwise, put the parameters in the function
2760 SetParameters(fFuncPars, fitFunc);
2761 }
2762
2763 if ( fParentPad ) fParentPad->Disconnect("RangeAxisChanged()");
2764 Int_t ret = 0;
2765 /// fit parameter dialog willbe deleted automatically when closed
2766 new TFitParametersDialog(gClient->GetDefaultRoot(), GetMainFrame(),
2767 fitFunc, fParentPad, &ret);
2768
2769 // Once the parameters are set in the fitfunction, save them.
2770 GetParameters(fFuncPars, fitFunc);
2771
2772 // check return code to see if parameters settings have been modified
2773 // in this case we need to set the B option when fitting
2774 if (ret) fChangedParams = kTRUE;
2775
2776
2777 if ( fParentPad ) fParentPad->Connect("RangeAxisChanged()", "TFitEditor", this, "UpdateGUI()");
2778
2779 if ( fNone->GetState() != kButtonDisabled ) {
2780 //std::cout << "TFitEditor::DoSetParameters - deleting function " << fitFunc->GetName() << " " << fitFunc << std::endl;
2781 delete fitFunc;
2782 }
2783}
2784
2785////////////////////////////////////////////////////////////////////////////////
2786/// Slot connected to range settings on x-axis.
2787
2789{
2790 if ( !fFitObject ) return;
2791
2794
2796
2797 DrawSelection();
2798}
2799
2800////////////////////////////////////////////////////////////////////////////////
2801/// Draws the square around the object showing where the limits for
2802/// fitting are.
2803
2805{
2806 static Int_t px1old, py1old, px2old, py2old; // to remember the square drawn.
2807
2808 if ( !fParentPad ) return;
2809
2810 if (restore) {
2815 return;
2816 }
2817
2818 Int_t px1,py1,px2,py2;
2819
2820 TVirtualPad *save = 0;
2821 save = gPad;
2822 gPad = fParentPad;
2823 gPad->cd();
2824
2825 Double_t xleft = 0;
2826 Double_t xright = 0;
2827 xleft = fXaxis->GetBinLowEdge((Int_t)((fSliderX->GetMinPosition())+0.5));
2828 xright = fXaxis->GetBinUpEdge((Int_t)((fSliderX->GetMaxPosition())+0.5));
2829
2830 Float_t ymin, ymax;
2831 if ( fDim > 1 )
2832 {
2833 ymin = fYaxis->GetBinLowEdge((Int_t)((fSliderY->GetMinPosition())+0.5));//gPad->GetUymin();
2834 ymax = fYaxis->GetBinUpEdge((Int_t)((fSliderY->GetMaxPosition())+0.5));//gPad->GetUymax();
2835 }
2836 else
2837 {
2838 ymin = gPad->GetUymin();
2839 ymax = gPad->GetUymax();
2840 }
2841
2842 px1 = gPad->XtoAbsPixel(xleft);
2843 py1 = gPad->YtoAbsPixel(ymin);
2844 px2 = gPad->XtoAbsPixel(xright);
2845 py2 = gPad->YtoAbsPixel(ymax);
2846
2847 if (gPad->GetCanvas()) gPad->GetCanvas()->FeedbackMode(kTRUE);
2848 gPad->SetLineWidth(1);
2849 gPad->SetLineColor(2);
2850#ifndef R__HAS_COCOA
2851 // With Cocoa XOR is fake, so no need in erasing the old box, it's
2852 // done by clearing the backing store and repainting inside a special
2853 // window.
2854 gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow);
2855#endif // R__HAS_COCOA
2856 gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2857
2858 px1old = px1;
2859 py1old = py1;
2860 px2old = px2 ;
2861 py2old = py2;
2862
2863 if(save) gPad = save;
2864}
2865
2866////////////////////////////////////////////////////////////////////////////////
2867/// Sincronize the numeric sliders with the graphical one.
2868
2870{
2872 float xmin, xmax;
2874 fSliderXMin->SetNumber( fXaxis->GetBinLowEdge( static_cast<Int_t>( xmin ) ) );
2875 fSliderXMax->SetNumber( fXaxis->GetBinUpEdge ( static_cast<Int_t>( xmax ) ) );
2876 return;
2877 }
2878
2881
2883
2884 DrawSelection();
2885}
2886
2887////////////////////////////////////////////////////////////////////////////////
2888/// Slot connected to range settings on y-axis.
2889
2891{
2892 if ( !fFitObject ) return;
2893
2896
2898
2899 DrawSelection();
2900}
2901
2902////////////////////////////////////////////////////////////////////////////////
2903///syncronize the numeric slider with the graphical one.
2904
2906{
2908 float ymin, ymax;
2910 fSliderYMin->SetNumber( fYaxis->GetBinLowEdge( static_cast<Int_t>( ymin ) ) );
2911 fSliderYMax->SetNumber( fYaxis->GetBinUpEdge ( static_cast<Int_t>( ymax ) ) );
2912 return;
2913 }
2914
2917
2919
2920 DrawSelection();
2921}
2922
2923////////////////////////////////////////////////////////////////////////////////
2924/// Slot connected to range settings on z-axis.
2925
2927{
2928}
2929
2930////////////////////////////////////////////////////////////////////////////////
2931/// Open a dialog for getting a user defined method.
2932
2934{
2936 "Info", "Dialog of user method is not implemented yet",
2938}
2939
2940////////////////////////////////////////////////////////////////////////////////
2941/// Set the function to be used in performed fit.
2942
2944{
2946}
2947
2948////////////////////////////////////////////////////////////////////////////////
2949/// Check whether the object suitable for fitting and set
2950/// its type, dimension and method combo box accordingly.
2951
2953{
2954 Bool_t set = kFALSE;
2955
2956 // For each kind of object, set a different status in the fit
2957 // panel.
2958 if (obj->InheritsFrom(TGraph::Class())) {
2960 set = kTRUE;
2961 fDim = 1;
2963 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
2966 fRobustValue->GetNumberEntry()->SetToolTipText("Set robust value");
2967 } else if (obj->InheritsFrom(TGraph2D::Class())) {
2969 set = kTRUE;
2970 fDim = 2;
2972 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
2974 } else if (obj->InheritsFrom(THStack::Class())) {
2976 set = kTRUE;
2977 TH1 *hist = (TH1 *)((THStack *)obj)->GetHists()->First();
2978 fDim = hist->GetDimension();
2980 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
2982 } else if (obj->InheritsFrom(TTree::Class())) {
2984 set = kTRUE;
2985 TString variables, cuts;
2987 fDim = 1;
2988 for ( int i = 0; i < variables.Length() && fDim <= 2; ++i )
2989 if ( ':' == variables[i] ) fDim += 1;
2990 // For any three of dimension bigger than 2, set the dimension
2991 // to 0, as we cannot infer the dimension from the TF1s, it's
2992 // better to have 0 as reference.
2993 if ( fDim > 2 ) fDim = 0;
2995 fMethodList->AddEntry("Unbinned Likelihood", kFP_MUBIN);
2997 } else if (obj->InheritsFrom(TH1::Class())){
2999 set = kTRUE;
3000 fDim = ((TH1*)obj)->GetDimension();
3002 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
3003 fMethodList->AddEntry("Binned Likelihood", kFP_MBINL);
3005 } else if (obj->InheritsFrom(TMultiGraph::Class())) {
3007 set = kTRUE;
3008 fDim = 1;
3010 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
3013 fRobustValue->GetNumberEntry()->SetToolTipText("Set robust value");
3014 }
3015
3016 // Depending on the dimension of the object, allow the
3017 // visualization of sliders.
3018 if ( fDim < 2 || fType == kObjectTree )
3020 else
3022
3023 if ( fDim < 1 || fType == kObjectTree )
3025 else
3027
3028 // And also, depending on the dimension, add predefined functions.
3029 if ( fDim == 1 ) {
3030 if ( !fTypeFit->FindEntry("Predef-1D") )
3032 } else {
3033 if ( fTypeFit->FindEntry("Predef-1D") )
3035 }
3036
3037 if ( fDim == 2 ) {
3038 if ( !fTypeFit->FindEntry("Predef-2D") )
3040 } else {
3041 if ( fTypeFit->FindEntry("Predef-2D") )
3043 }
3044
3045 return set;
3046}
3047
3048////////////////////////////////////////////////////////////////////////////////
3049/// Show object name on the top.
3050
3052{
3053 TString name;
3054 bool isTree = false;
3055
3056 // Build the string to be compared to look for the object.
3057 if (obj) {
3058 name = obj->ClassName();
3059 name.Append("::");
3060 name.Append(obj->GetName());
3061 isTree = strcmp(obj->ClassName(), "TTree") == 0;
3062 } else {
3063 name = "No object selected";
3064 }
3065 fStatusBar->SetText(name.Data(),0);
3066
3067 // If the selection was done in the fDataSet combo box, there is no need
3068 // to search through the list
3069 TGTextLBEntry* selectedEntry = static_cast<TGTextLBEntry*> ( fDataSet->GetSelectedEntry());
3070 if ( selectedEntry ) {
3071 TString selectedName = selectedEntry->GetText()->GetString();
3072 if ( isTree )
3073 selectedName = selectedName(0, selectedName.First(' '));
3074 if ( name.CompareTo(selectedName) == 0 ) {
3075 Layout();
3076 return;
3077 }
3078 }
3079
3080 // Search through the list for the object
3081 Int_t entryId = kFP_NOSEL+1;
3082 bool found = false;
3083 while ( TGTextLBEntry* entry = static_cast<TGTextLBEntry*>
3084 ( fDataSet->GetListBox()->GetEntry(entryId)) ) {
3085 TString compareName = entry->GetText()->GetString();
3086 if ( isTree )
3087 compareName = compareName(0, compareName.First(' '));
3088 if ( name.CompareTo(compareName) == 0 ) {
3089 // If the object is found, select it
3090 fDataSet->Select(entryId, false);
3091 found = true;
3092 break;
3093 }
3094 entryId += 1;
3095 }
3096
3097 // If the object was not found, add it and select it.
3098 if ( !found ) {
3099 fDataSet->AddEntry(name.Data(), entryId);
3100 fDataSet->Select(entryId, kTRUE);
3101 }
3102
3103 Layout();
3104}
3105
3106////////////////////////////////////////////////////////////////////////////////
3107/// Get draw options of the selected object.
3108
3110{
3111 if (!fParentPad) return "";
3112
3114 TObject *obj;
3115 while ((obj = next())) {
3116 if (obj == fFitObject) return next.GetOption();
3117 }
3118 return "";
3119}
3120
3121////////////////////////////////////////////////////////////////////////////////
3122/// Set selected minimization library in use.
3123
3125{
3126 TGButton *bt = (TGButton *)gTQSender;
3127 Int_t id = bt->WidgetId();
3128
3129 switch (id) {
3130
3131 // Depending on the selected library, set the state of the rest
3132 // of the buttons.
3133 case kFP_LMIN:
3134 {
3135 if (on) {
3139 if ( fLibGSL->GetState() != kButtonDisabled )
3143 fStatusBar->SetText("LIB Minuit", 1);
3144 }
3145
3146 }
3147 break;
3148
3149 case kFP_LMIN2:
3150 {
3151 if (on) {
3155 if ( fLibGSL->GetState() != kButtonDisabled )
3159 fStatusBar->SetText("LIB Minuit2", 1);
3160 }
3161 }
3162 break;
3163
3164 case kFP_LFUM:
3165 {
3166 if (on) {
3170 if ( fLibGSL->GetState() != kButtonDisabled )
3174 fStatusBar->SetText("LIB Fumili", 1);
3175 }
3176 }
3177 break;
3178 case kFP_LGSL:
3179 {
3180 if (on) {
3184 if ( fLibGSL->GetState() != kButtonDisabled )
3188 fStatusBar->SetText("LIB GSL", 1);
3189 }
3190 }
3191 break;
3192 case kFP_LGAS:
3193 {
3194 if (on) {
3198 if ( fLibGSL->GetState() != kButtonDisabled )
3202 fStatusBar->SetText("LIB Genetics", 1);
3203 }
3204 }
3205 default:
3206 break;
3207 }
3209}
3210
3211////////////////////////////////////////////////////////////////////////////////
3212/// Set selected minimization method in use.
3213
3215{
3217 fStatusBar->SetText("MIGRAD",2);
3218 else if ( fMinMethodList->GetSelected() == kFP_FUMILI)
3219 fStatusBar->SetText("FUMILI",2);
3220 else if ( fMinMethodList->GetSelected() == kFP_SIMPLX )
3221 fStatusBar->SetText("SIMPLEX",2);
3222 else if ( fMinMethodList->GetSelected() == kFP_SCAN )
3223 fStatusBar->SetText("SCAN",2);
3225 fStatusBar->SetText("Combination",2);
3226 else if ( fMinMethodList->GetSelected() == kFP_GSLFR )
3227 fStatusBar->SetText("CONJFR",2);
3228 else if ( fMinMethodList->GetSelected() == kFP_GSLPR )
3229 fStatusBar->SetText("CONJPR",2);
3230 else if ( fMinMethodList->GetSelected() == kFP_BFGS )
3231 fStatusBar->SetText("BFGS",2);
3232 else if ( fMinMethodList->GetSelected() == kFP_BFGS2 )
3233 fStatusBar->SetText("BFGS2",2);
3234 else if ( fMinMethodList->GetSelected() == kFP_GSLLM )
3235 fStatusBar->SetText("GSLLM",2);
3236 else if ( fMinMethodList->GetSelected() == kFP_GSLSA)
3237 fStatusBar->SetText("SimAn",2);
3238 else if ( fMinMethodList->GetSelected() == kFP_TMVAGA )
3239 fStatusBar->SetText("TMVAGA",2);
3240 else if ( fMinMethodList->GetSelected() == kFP_GALIB )
3241 fStatusBar->SetText("GALIB",2);
3242
3243
3244}
3245
3246////////////////////////////////////////////////////////////////////////////////
3247/// Set the maximum number of iterations.
3248
3250{
3252 fStatusBar->SetText(Form("Itr: %ld",itr),2);
3253}
3254
3255////////////////////////////////////////////////////////////////////////////////
3256/// Create section title in the GUI.
3257
3258void TFitEditor::MakeTitle(TGCompositeFrame *parent, const char *title)
3259{
3260 TGCompositeFrame *ht = new TGCompositeFrame(parent, 350, 10,
3262 ht->AddFrame(new TGLabel(ht, title),
3263 new TGLayoutHints(kLHintsLeft, 1, 1, 0, 0));
3264 ht->AddFrame(new TGHorizontal3DLine(ht),
3265 new TGLayoutHints(kLHintsExpandX | kLHintsCenterY, 5, 5, 2, 2));
3266 parent->AddFrame(ht, new TGLayoutHints(kLHintsTop, 5, 0, 5, 0));
3267}
3268
3269////////////////////////////////////////////////////////////////////////////////
3270/// Look in the list of function for TF1. If a TF1 is
3271/// found in the list of functions, it will be returned
3272
3274{
3275 // Get the list of functions of the fit object
3277 TF1* func = 0;
3278
3279 // If it exists
3280 if ( lf ) {
3281 // Add the posibility to select previous fit function
3282 if ( !fTypeFit->FindEntry("Prev. Fit") )
3284
3285 // Then add all these functions to the fPrefFit structure.
3286 TObject *obj2;
3287 TIter next(lf, kIterForward);
3288 // Go over all the elements in lf
3289 while ((obj2 = next())) {
3290 if (obj2->InheritsFrom(TF1::Class())) {
3291 func = (TF1 *)obj2;
3292 fPrevFitIter it;
3293 // No go over all elements in fPrevFit
3294 for ( it = fPrevFit.begin(); it != fPrevFit.end(); ++it) {
3295 // To see wheather the object corresponds with fFitObject
3296 if ( it->first != fFitObject ) continue;
3297 // And if so, whether the function is already included
3298 if ( strcmp( func->GetName(), it->second->GetName() ) == 0 )
3299 break;
3300 if ( strcmp( func->GetName(), "PrevFitTMP" ) == 0 )
3301 break;
3302 }
3303 // Only if the function is not already in fPrevFit, the
3304 // breaks in the loops would make it to be different to
3305 // fPrevFit.end() if the function is already stored
3306 if ( it == fPrevFit.end() ) {
3307 fPrevFit.emplace(fFitObject, copyTF1(func));
3308 }
3309 }
3310 }
3311
3312 // Select the PrevFit set
3314 // And fill the function list
3317
3318
3319 } else {
3320 // If there is no prev fit functions.
3322 // Call FillFunctionList as it might happen that the user is
3323 // changing from a TTree to another one, and thus the fFuncList
3324 // if not properly filled
3326 }
3327
3329
3330 return func;
3331}
3332
3333////////////////////////////////////////////////////////////////////////////////
3334/// Retrieve the fitting options from all the widgets.
3335
3337{
3338 drawOpts = "";
3339
3340 fitOpts.Range = (fUseRange->GetState() == kButtonDown);
3341 fitOpts.Integral = (fIntegral->GetState() == kButtonDown);
3342 fitOpts.More = (fImproveResults->GetState() == kButtonDown);
3343 fitOpts.Errors = (fBestErrors->GetState() == kButtonDown);
3344 fitOpts.Like = (fMethodList->GetSelected() != kFP_MCHIS);
3345
3347 fitOpts.W1 = 2;
3348 else if (fAllWeights1->GetState() == kButtonDown)
3349 fitOpts.W1 = 1;
3350
3351 TString tmpStr = fEnteredFunc->GetText();
3352 if ( !(fLinearFit->GetState() == kButtonDown) &&
3353 (tmpStr.Contains("pol") || tmpStr.Contains("++")) )
3354 fitOpts.Minuit = 1;
3355
3356 // if ( (int) fFuncPars.size() == npar )
3357 // for ( Int_t i = 0; i < npar; ++i )
3358 // if ( fFuncPars[i][PAR_MIN] != fFuncPars[i][PAR_MAX] )
3359 //
3360
3361 // //fitOpts.Bound = 1;
3362 // break;
3363 // }
3364
3365 if (fChangedParams) {
3366 //std::cout << "Params have changed setting the Bound option " << std::endl;
3367 fitOpts.Bound = 1;
3368 fChangedParams = kFALSE; // reset
3369 }
3370
3371 //fitOpts.Nochisq = (fNoChi2->GetState() == kButtonDown);
3372 fitOpts.Nostore = (fNoStoreDrawing->GetState() == kButtonDown);
3373 fitOpts.Nograph = (fNoDrawing->GetState() == kButtonDown);
3374 fitOpts.Plus = (fAdd2FuncList->GetState() == kButtonDown);
3375 fitOpts.Gradient = (fUseGradient->GetState() == kButtonDown);
3376 fitOpts.Quiet = ( fOptQuiet->GetState() == kButtonDown );
3377 fitOpts.Verbose = ( fOptVerbose->GetState() == kButtonDown );
3378
3379 if ( !(fType != kObjectGraph) && (fEnableRobust->GetState() == kButtonDown) )
3380 {
3381 fitOpts.Robust = 1;
3382 fitOpts.hRobust = fRobustValue->GetNumber();
3383 }
3384
3385 drawOpts = GetDrawOption();
3386
3387 if ( fLibMinuit->GetState() == kButtonDown )
3388 minOpts.SetMinimizerType ( "Minuit");
3389 else if ( fLibMinuit2->GetState() == kButtonDown)
3390 minOpts.SetMinimizerType ( "Minuit2" );
3391 else if ( fLibFumili->GetState() == kButtonDown )
3392 minOpts.SetMinimizerType ("Fumili" );
3393 else if ( fLibGSL->GetState() == kButtonDown )
3394 minOpts.SetMinimizerType ("GSLMultiMin" );
3395
3397 minOpts.SetMinimizerAlgorithm( "Migrad" );
3398 else if ( fMinMethodList->GetSelected() == kFP_FUMILI)
3399 if ( fLibMinuit2->GetState() == kButtonDown )
3400 minOpts.SetMinimizerAlgorithm( "Fumili2" );
3401 else
3402 minOpts.SetMinimizerAlgorithm( "Fumili" );
3403 else if ( fMinMethodList->GetSelected() == kFP_SIMPLX )
3404 minOpts.SetMinimizerAlgorithm( "Simplex" );
3405 else if ( fMinMethodList->GetSelected() == kFP_SCAN )
3406 minOpts.SetMinimizerAlgorithm( "Scan" );
3408 minOpts.SetMinimizerAlgorithm( "Minimize" );
3409 else if ( fMinMethodList->GetSelected() == kFP_GSLFR )
3410 minOpts.SetMinimizerAlgorithm( "conjugatefr" );
3411 else if ( fMinMethodList->GetSelected() == kFP_GSLPR )
3412 minOpts.SetMinimizerAlgorithm( "conjugatepr" );
3413 else if ( fMinMethodList->GetSelected() == kFP_BFGS )
3414 minOpts.SetMinimizerAlgorithm( "bfgs" );
3415 else if ( fMinMethodList->GetSelected() == kFP_BFGS2 )
3416 minOpts.SetMinimizerAlgorithm( "bfgs2" );
3417 else if ( fMinMethodList->GetSelected() == kFP_GSLLM ) {
3418 minOpts.SetMinimizerType ("GSLMultiFit" );
3419 minOpts.SetMinimizerAlgorithm( "" );
3420 } else if ( fMinMethodList->GetSelected() == kFP_GSLSA) {
3421 minOpts.SetMinimizerType ("GSLSimAn" );
3422 minOpts.SetMinimizerAlgorithm( "" );
3423 } else if ( fMinMethodList->GetSelected() == kFP_TMVAGA) {
3424 minOpts.SetMinimizerType ("Geneti2c" );
3425 minOpts.SetMinimizerAlgorithm( "" );
3426 } else if ( fMinMethodList->GetSelected() == kFP_GALIB) {
3427 minOpts.SetMinimizerType ("GAlibMin" );
3428 minOpts.SetMinimizerAlgorithm( "" );
3429 }
3430
3431 minOpts.SetErrorDef ( fErrorScale->GetNumber() );
3432 minOpts.SetTolerance( fTolerance->GetNumber() );
3435}
3436
3438{
3439 // Set the state of some input widgets depending on whether the fit
3440 // function can be defined by text or if it is an existing one.
3441 if ( state )
3442 {
3443 fEnteredFunc-> SetState(kTRUE);
3444 fAdd -> SetState(kButtonUp, kFALSE);
3445 fNormAdd -> SetState(kButtonUp, kFALSE);
3446 fConv -> SetState(kButtonUp, kFALSE);
3447 fNone -> SetState(kButtonDown,kFALSE); // fNone::State is the one used as reference
3448 }
3449 else
3450 {
3451 fEnteredFunc-> SetState(kFALSE);
3452 fAdd -> SetState(kButtonDisabled, kFALSE);
3453 fNormAdd -> SetState(kButtonDisabled, kFALSE);
3454 fConv -> SetState(kButtonDisabled, kFALSE);
3455 fNone -> SetState(kButtonDisabled, kFALSE);
3456 }
3457}
3458
3460{
3461 // Return the ranges selected by the sliders.
3462
3463 // It's not working for trees as they don't have TAxis.
3464 if ( fType == kObjectTree ) return;
3465
3466 if ( fType != kObjectTree ) {
3467 Int_t ixmin = (Int_t)(fSliderX->GetMinPosition());
3468 Int_t ixmax = (Int_t)(fSliderX->GetMaxPosition());
3470 Double_t xmax = fXaxis->GetBinUpEdge(ixmax);
3471 drange.AddRange(0,xmin, xmax);
3472 }
3473
3474 if ( fDim > 1 ) {
3475 assert(fYaxis);
3476 Int_t iymin = (Int_t)(fSliderY->GetMinPosition());
3477 Int_t iymax = (Int_t)(fSliderY->GetMaxPosition());
3479 Double_t ymax = fYaxis->GetBinUpEdge(iymax);
3480 drange.AddRange(1,ymin, ymax);
3481 }
3482 if ( fDim > 2 ) {
3483 assert(fZaxis);
3484 Int_t izmin = (Int_t)(fSliderZ->GetMinPosition());
3485 Int_t izmax = (Int_t)(fSliderZ->GetMaxPosition());
3486 Double_t zmin = fZaxis->GetBinLowEdge(izmin);
3487 Double_t zmax = fZaxis->GetBinUpEdge(izmax);
3488 drange.AddRange(2,zmin, zmax);
3489 }
3490}
3491
3493{
3494 // Get the list of functions previously used in the fitobject.
3495
3496 TList *listOfFunctions = 0;
3497 if ( fFitObject ) {
3498 switch (fType) {
3499
3500 case kObjectHisto:
3501 listOfFunctions = ((TH1 *)fFitObject)->GetListOfFunctions();
3502 break;
3503
3504 case kObjectGraph:
3505 listOfFunctions = ((TGraph *)fFitObject)->GetListOfFunctions();
3506 break;
3507
3508 case kObjectMultiGraph:
3509 listOfFunctions = ((TMultiGraph *)fFitObject)->GetListOfFunctions();
3510 break;
3511
3512 case kObjectGraph2D:
3513 listOfFunctions = ((TGraph2D *)fFitObject)->GetListOfFunctions();
3514 break;
3515
3516 case kObjectHStack:
3517 case kObjectTree:
3518 default:
3519 break;
3520 }
3521 }
3522 return listOfFunctions;
3523}
3524
3526{
3527 // Looks for all the functions registered in the current ROOT
3528 // session.
3529
3530 // First, clean the copies stored in fSystemFunc
3531 for (auto func : fSystemFuncs)
3532 delete func;
3533
3534 fSystemFuncs.clear();
3535
3536 // Be carefull not to store functions that will be in the
3537 // predefined section
3538 const unsigned int nfuncs = 16;
3539 const char* fnames[nfuncs] = { "gaus" , "gausn", "expo", "landau",
3540 "landaun", "pol0", "pol1", "pol2",
3541 "pol3", "pol4", "pol5", "pol6",
3542 "pol7", "pol8", "pol9", "user"
3543 };
3544
3545 // No go through all the objects registered in gROOT
3546 TIter functionsIter(gROOT->GetListOfFunctions());
3547 TObject* obj;
3548 while( ( obj = (TObject*) functionsIter() ) ) {
3549 // And if they are TF1s
3550 if ( TF1* func = dynamic_cast<TF1*>(obj) ) {
3551 bool addFunction = true;
3552 // And they are not already registered in fSystemFunc
3553 for ( unsigned int i = 0; i < nfuncs; ++i ) {
3554 if ( strcmp( func->GetName(), fnames[i] ) == 0 ) {
3555 addFunction = false;
3556 break;
3557 }
3558 }
3559 // Add them.
3560 if ( addFunction )
3561 fSystemFuncs.emplace_back( copyTF1(func) );
3562 }
3563 }
3564}
3565
3567{
3568 // This function returns a TList with all the functions used in the
3569 // FitPanel to fit a given object. If the object passed is NULL,
3570 // then the object used is the currently selected one. It is
3571 // important to notice that the FitPanel is still the owner of
3572 // those functions. This means that the user SHOULD NOT delete any
3573 // of these functions, as the FitPanel will do so in the
3574 // destructor.
3575
3576 if (!obj) obj = fFitObject;
3577
3578 TList *retList = new TList();
3579
3580 std::pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(obj);
3581 for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
3582 retList->Add(it->second);
3583 }
3584
3585 return retList;
3586}
3587
3589{
3590 // Get the fit function selected or declared in the fiteditor
3591
3592 TF1 *fitFunc = 0;
3593 // If the function is not editable ==> it means it is registered in
3594 // gROOT
3595 if ( fNone->GetState() == kButtonDisabled )
3596 {
3597 // So we find it
3598 TF1* tmpF1 = FindFunction();
3599 // And if we don't find it, then it means there is something wrong!
3600 if ( tmpF1 == 0 )
3601 {
3603 "Error...", "1) Verify the entered function string!",
3604 kMBIconStop,kMBOk, 0);
3605 return 0;
3606 }
3607
3608 // Now we make a copy that will be used temporary. The caller of
3609 // the function should delete the returned function.
3610 fitFunc = (TF1*)tmpF1->IsA()->New();
3611 tmpF1->Copy(*fitFunc);
3612 // Copy the parameters of the function, if and only if the
3613 // parameters stored does not correspond with the ones of these
3614 // functions. Perhaps the user has already called
3615 // DoSetParameters. There is no way to know whether the
3616 // parameters have been modified, so we check the size of
3617 // fFuncPars against number of parameters.
3618 if ( int(fFuncPars.size()) != tmpF1->GetNpar() )
3619 {
3620 fitFunc->SetParameters(tmpF1->GetParameters());
3621 GetParameters(fFuncPars, fitFunc);
3622 } else {
3623 SetParameters(fFuncPars, fitFunc);
3624 }
3625 }
3626
3627 // If, we have no function at this point, it means that is is
3628 // described in fEnteredFunc, so we create it from scratch.
3629 if ( fitFunc == 0 )
3630 {
3631 ROOT::Fit::DataRange drange;
3632 GetRanges(drange);
3633 double xmin, xmax, ymin, ymax, zmin, zmax;
3634 drange.GetRange(xmin, xmax, ymin, ymax, zmin, zmax);
3635
3636 // Depending of course on the number of dimensions the object
3637 // has. These commands will raise an error message if the user
3638 // has not defined the function properly
3639 if ( fDim == 1 || fDim == 0 )
3640 {
3641
3642 fitFunc = new TF1("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax );
3643 //std::cout << "GetFitFunction - created function PrevFitTMP " << fEnteredFunc->GetText() << " " << fitFunc << std::endl;
3644 if (fNormAdd->IsOn())
3645 {
3646 if (fSumFunc) delete fSumFunc;
3648 fitFunc = new TF1("PrevFitTMP", *fSumFunc, xmin, xmax, fSumFunc->GetNpar());
3649 for (int i = 0; i < fitFunc->GetNpar(); ++i) fitFunc->SetParName(i, fSumFunc->GetParName(i) );
3650 //std::cout << "create fit normalized function " << fSumFunc << " fitfunc " << fitFunc << std::endl;
3651 }
3652
3653 if (fConv -> IsOn())
3654 {
3655 if (fConvFunc) delete fConvFunc;
3657 fitFunc = new TF1("PrevFitTMP", *fConvFunc, xmin, xmax, fConvFunc->GetNpar());
3658 for (int i = 0; i < fitFunc->GetNpar(); ++i) fitFunc->SetParName(i, fConvFunc->GetParName(i) );
3659 //std::cout << "create fit convolution function " << fSumFunc << " fitfunc " << fitFunc << std::endl;
3660 }
3661 }
3662 else if ( fDim == 2 ) {
3663 fitFunc = new TF2("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax, ymin, ymax );
3664 }
3665 else if ( fDim == 3 ) {
3666 fitFunc = new TF3("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax, ymin, ymax, zmin, zmax );
3667 }
3668
3669 // if the function is not a C defined
3670 if ( fNone->GetState() != kButtonDisabled )
3671 {
3672 // and the formulas are the same
3673 TF1* tmpF1 = FindFunction();
3674// if (tmpF1)
3675 //std::cout << "GetFitFunction: found existing function " << tmpF1 << " " << tmpF1->GetName() << " " << tmpF1->GetExpFormula() << std::endl;
3676// else
3677 //std::cout << "GetFitFunction: - no existing function found " << std::endl;
3678 if ( tmpF1 != 0 && fitFunc != 0 &&
3679 strcmp(tmpF1->GetExpFormula(), fEnteredFunc->GetText()) == 0 ) {
3680 // copy everything from the founction available in gROOT
3681 //std::cout << "GetFitFunction: copying tmp function in PrevFitTMP " << tmpF1->GetName() << " "
3682 // << tmpF1->GetExpFormula() << std::endl;
3683 tmpF1->Copy(*fitFunc);
3684 if ( int(fFuncPars.size()) != tmpF1->GetNpar() )
3685 {
3686 GetParameters(fFuncPars, fitFunc);
3687 }
3688 }
3689 }
3690 }
3691
3692 return fitFunc;
3693}
@ kButton1Down
Definition: Buttons.h:17
void Class()
Definition: Class.C:29
@ kVerticalFrame
Definition: GuiTypes.h:381
@ kFixedWidth
Definition: GuiTypes.h:387
@ kFitWidth
Definition: GuiTypes.h:386
@ kHorizontalFrame
Definition: GuiTypes.h:382
@ kFixedSize
Definition: GuiTypes.h:390
@ kWatch
Definition: GuiTypes.h:375
@ kPointer
Definition: GuiTypes.h:375
ULong_t Pixel_t
Pixel value.
Definition: GuiTypes.h:40
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define s1(x)
Definition: RSha256.hxx:91
#define h(i)
Definition: RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
int Int_t
Definition: RtypesCore.h:45
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
bool Bool_t
Definition: RtypesCore.h:63
double Double_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:80
float Float_t
Definition: RtypesCore.h:57
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:364
const Bool_t kIterForward
Definition: TCollection.h:42
#define gDirectory
Definition: TDirectory.h:348
#define R__ASSERT(e)
Definition: TError.h:118
TF1 * copyTF1(TF1 *f)
Copies f into a new TF1 to be stored in the fitpanel with it's own ownership.
Definition: TFitEditor.cxx:216
void GetParameters(TFitEditor::FuncParams_t &pars, TF1 *func)
Stores the parameters of the given function into pars.
Definition: TFitEditor.cxx:256
void InitParameters(TF1 *func, FitObject *fitobj)
Parameter initialization for the function.
Definition: TFitEditor.cxx:288
void GetTreeVarsAndCuts(TGComboBox *dataSet, TString &variablesStr, TString &cutsStr)
Splits the entry in fDataSet to get the selected variables and cuts from the text.
Definition: TFitEditor.cxx:307
void SetParameters(TFitEditor::FuncParams_t &pars, TF1 *func)
Restore the parameters from pars into the function.
Definition: TFitEditor.cxx:273
void SearchCanvases(TSeqCollection *canvases, std::vector< TObject * > &objects)
std::multimap< TObject *, TF1 * > FitFuncMap_t
Definition: TFitEditor.cxx:173
@ kObjectMultiGraph
Definition: TFitEditor.h:33
@ kObjectGraph
Definition: TFitEditor.h:29
@ kObjectHStack
Definition: TFitEditor.h:31
@ kObjectHisto
Definition: TFitEditor.h:28
@ kObjectGraph2D
Definition: TFitEditor.h:30
@ kObjectTree
Definition: TFitEditor.h:32
@ kButtonDown
Definition: TGButton.h:54
@ kButtonDisabled
Definition: TGButton.h:56
@ kButtonUp
Definition: TGButton.h:53
@ kButtonEngaged
Definition: TGButton.h:55
#define gClient
Definition: TGClient.h:157
@ kDoubleScaleBoth
@ kMWMDecorResizeH
Definition: TGFrame.h:65
@ kMWMFuncAll
Definition: TGFrame.h:49
@ kMWMFuncResize
Definition: TGFrame.h:50
@ kMWMDecorMaximize
Definition: TGFrame.h:69
@ kMWMDecorMinimize
Definition: TGFrame.h:68
@ kMWMDecorMenu
Definition: TGFrame.h:67
@ kMWMDecorAll
Definition: TGFrame.h:63
@ kMWMFuncMaximize
Definition: TGFrame.h:53
@ kMWMInputModeless
Definition: TGFrame.h:57
@ kMWMFuncMinimize
Definition: TGFrame.h:52
@ kDeepCleanup
Definition: TGFrame.h:42
@ kLHintsRight
Definition: TGLayout.h:26
@ kLHintsExpandY
Definition: TGLayout.h:31
@ kLHintsLeft
Definition: TGLayout.h:24
@ kLHintsCenterY
Definition: TGLayout.h:28
@ kLHintsNormal
Definition: TGLayout.h:32
@ kLHintsBottom
Definition: TGLayout.h:29
@ kLHintsTop
Definition: TGLayout.h:27
@ kLHintsExpandX
Definition: TGLayout.h:30
@ kMBOk
Definition: TGMsgBox.h:33
@ kMBIconAsterisk
Definition: TGMsgBox.h:25
@ kMBIconStop
Definition: TGMsgBox.h:22
@ kTextLeft
Definition: TGWidget.h:23
char name[80]
Definition: TGX11.cxx:110
float xmin
Definition: THbookFile.cxx:95
float ymin
Definition: THbookFile.cxx:95
float xmax
Definition: THbookFile.cxx:95
float ymax
Definition: THbookFile.cxx:95
R__EXTERN TPluginManager * gPluginMgr
R__EXTERN void * gTQSender
Definition: TQObject.h:44
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
#define gPad
Definition: TVirtualPad.h:288
#define gVirtualX
Definition: TVirtualX.h:338
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition: BinData.h:52
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition: DataRange.h:35
void AddRange(unsigned int icoord, double xmin, double xmax)
add a range [xmin,xmax] for the new coordinate icoord Adding a range does not delete existing one,...
Definition: DataRange.cxx:94
void GetRange(unsigned int irange, unsigned int icoord, double &xmin, double &xmax) const
get the i-th range for given coordinate.
Definition: DataRange.h:104
unsigned int Size() const
return number of fit points
Definition: FitData.h:303
const double * Coords(unsigned int ipoint) const
return a pointer to the coordinates data for the given fit point
Definition: FitData.h:246
Class describing the unbinned data sets (just x coordinates values) of any dimensions.
Definition: UnBinData.h:42
void SetMaxFunctionCalls(unsigned int maxfcn)
set maximum of function calls
void SetMaxIterations(unsigned int maxiter)
set maximum iterations (one iteration can have many function calls)
void SetMinimizerType(const char *type)
set minimizer type
static const std::string & DefaultMinimizerType()
void SetErrorDef(double err)
set error def
void SetMinimizerAlgorithm(const char *type)
set minimizer algorithm
void SetTolerance(double tol)
set the tolerance
Allows to create advanced graphics from the last fit made in the fitpanel.
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:518
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:469
Int_t GetNbins() const
Definition: TAxis.h:121
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:528
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:458
The Canvas class.
Definition: TCanvas.h:23
Int_t GetWindowTopX()
Returns current top x position of window on screen.
Definition: TCanvas.cxx:1199
Int_t GetWindowTopY()
Returns current top y position of window on screen.
Definition: TCanvas.cxx:1210
virtual void Selected(TVirtualPad *pad, TObject *obj, Int_t event)
Emit Selected() signal.
Definition: TCanvas.cxx:1639
void SetCursor(ECursor cursor) override
Set cursor.
Definition: TCanvas.cxx:2006
UInt_t GetWindowWidth() const
Definition: TCanvas.h:159
Class wrapping convolution of two functions.
Int_t GetNpar() const
const char * GetParName(Int_t ipar) const
Class adding two functions: c1*f1+c2*f2.
Definition: TF1NormSum.h:19
const char * GetParName(Int_t ipar) const
Definition: TF1NormSum.h:66
Int_t GetNpar() const
Return the number of (non constant) parameters including the coefficients: for 2 functions: c1,...
Definition: TF1NormSum.cxx:363
1-Dim function class
Definition: TF1.h:213
virtual Int_t GetNumber() const
Definition: TF1.h:498
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition: TF1.cxx:1936
virtual void Copy(TObject &f1) const
Copy this F1 to a new F1.
Definition: TF1.cxx:1000
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition: TF1.cxx:3539
virtual void SetParent(TObject *p=0)
Definition: TF1.h:665
virtual Int_t GetNpar() const
Definition: TF1.h:481
virtual TString GetExpFormula(Option_t *option="") const
Definition: TF1.h:461
virtual Double_t * GetParameters() const
Definition: TF1.h:520
virtual void GetRange(Double_t *xmin, Double_t *xmax) const
Return range of a generic N-D function.
Definition: TF1.cxx:2275
virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
Set limits for parameter ipar.
Definition: TF1.cxx:3518
virtual void SetParName(Int_t ipar, const char *name)
Set name of parameter number ipar.
Definition: TF1.cxx:3470
virtual void Draw(Option_t *option="")
Draw this function with its current attributes.
Definition: TF1.cxx:1328
virtual Bool_t IsValid() const
Return kTRUE if the function is valid.
Definition: TF1.cxx:2872
virtual void SetParameters(const Double_t *params)
Definition: TF1.h:644
virtual void SetParameter(Int_t param, Double_t value)
Definition: TF1.h:634
virtual void Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
Save values of function in array fSave.
Definition: TF1.cxx:3154
virtual Bool_t AddToGlobalList(Bool_t on=kTRUE)
Add to global list of functions (gROOT->GetListOfFunctions() ) return previous status (true if the fu...
Definition: TF1.cxx:841
virtual Double_t GetParameter(Int_t ipar) const
Definition: TF1.h:512
A 2-Dim function with parameters.
Definition: TF2.h:29
virtual void Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_