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);
295 // case gaussian or Landau
296 } else if ( 110 == special || 410 == special ) {
298 ROOT::Fit::FillData(data,fitobj,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#ifndef R__HAS_COCOA
2807 static Int_t px1old, py1old, px2old, py2old; // to remember the square drawn.
2808#endif
2809
2810 if ( !fParentPad ) return;
2811
2812 if (restore) {
2813#ifndef R__HAS_COCOA
2818#endif
2819 return;
2820 }
2821
2822 Int_t px1,py1,px2,py2;
2823
2824 TVirtualPad *save = 0;
2825 save = gPad;
2826 gPad = fParentPad;
2827 gPad->cd();
2828
2829 Double_t xleft = 0;
2830 Double_t xright = 0;
2831 xleft = fXaxis->GetBinLowEdge((Int_t)((fSliderX->GetMinPosition())+0.5));
2832 xright = fXaxis->GetBinUpEdge((Int_t)((fSliderX->GetMaxPosition())+0.5));
2833
2834 Float_t ymin, ymax;
2835 if ( fDim > 1 )
2836 {
2837 ymin = fYaxis->GetBinLowEdge((Int_t)((fSliderY->GetMinPosition())+0.5));//gPad->GetUymin();
2838 ymax = fYaxis->GetBinUpEdge((Int_t)((fSliderY->GetMaxPosition())+0.5));//gPad->GetUymax();
2839 }
2840 else
2841 {
2842 ymin = gPad->GetUymin();
2843 ymax = gPad->GetUymax();
2844 }
2845
2846 px1 = gPad->XtoAbsPixel(xleft);
2847 py1 = gPad->YtoAbsPixel(ymin);
2848 px2 = gPad->XtoAbsPixel(xright);
2849 py2 = gPad->YtoAbsPixel(ymax);
2850
2851 if (gPad->GetCanvas()) gPad->GetCanvas()->FeedbackMode(kTRUE);
2852 gPad->SetLineWidth(1);
2853 gPad->SetLineColor(2);
2854#ifndef R__HAS_COCOA
2855 // With Cocoa XOR is fake, so no need in erasing the old box, it's
2856 // done by clearing the backing store and repainting inside a special
2857 // window.
2858 gVirtualX->DrawBox(px1old, py1old, px2old, py2old, TVirtualX::kHollow);
2859
2860 px1old = px1;
2861 py1old = py1;
2862 px2old = px2;
2863 py2old = py2;
2864#endif // R__HAS_COCOA
2865 gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
2866
2867 if(save) gPad = save;
2868}
2869
2870////////////////////////////////////////////////////////////////////////////////
2871/// Sincronize the numeric sliders with the graphical one.
2872
2874{
2876 float xmin, xmax;
2878 fSliderXMin->SetNumber( fXaxis->GetBinLowEdge( static_cast<Int_t>( xmin ) ) );
2879 fSliderXMax->SetNumber( fXaxis->GetBinUpEdge ( static_cast<Int_t>( xmax ) ) );
2880 return;
2881 }
2882
2885
2887
2888 DrawSelection();
2889}
2890
2891////////////////////////////////////////////////////////////////////////////////
2892/// Slot connected to range settings on y-axis.
2893
2895{
2896 if ( !fFitObject ) return;
2897
2900
2902
2903 DrawSelection();
2904}
2905
2906////////////////////////////////////////////////////////////////////////////////
2907///syncronize the numeric slider with the graphical one.
2908
2910{
2912 float ymin, ymax;
2914 fSliderYMin->SetNumber( fYaxis->GetBinLowEdge( static_cast<Int_t>( ymin ) ) );
2915 fSliderYMax->SetNumber( fYaxis->GetBinUpEdge ( static_cast<Int_t>( ymax ) ) );
2916 return;
2917 }
2918
2921
2923
2924 DrawSelection();
2925}
2926
2927////////////////////////////////////////////////////////////////////////////////
2928/// Slot connected to range settings on z-axis.
2929
2931{
2932}
2933
2934////////////////////////////////////////////////////////////////////////////////
2935/// Open a dialog for getting a user defined method.
2936
2938{
2940 "Info", "Dialog of user method is not implemented yet",
2942}
2943
2944////////////////////////////////////////////////////////////////////////////////
2945/// Set the function to be used in performed fit.
2946
2948{
2950}
2951
2952////////////////////////////////////////////////////////////////////////////////
2953/// Check whether the object suitable for fitting and set
2954/// its type, dimension and method combo box accordingly.
2955
2957{
2958 Bool_t set = kFALSE;
2959
2960 // For each kind of object, set a different status in the fit
2961 // panel.
2962 if (obj->InheritsFrom(TGraph::Class())) {
2964 set = kTRUE;
2965 fDim = 1;
2967 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
2970 fRobustValue->GetNumberEntry()->SetToolTipText("Set robust value");
2971 } else if (obj->InheritsFrom(TGraph2D::Class())) {
2973 set = kTRUE;
2974 fDim = 2;
2976 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
2978 } else if (obj->InheritsFrom(THStack::Class())) {
2980 set = kTRUE;
2981 TH1 *hist = (TH1 *)((THStack *)obj)->GetHists()->First();
2982 fDim = hist->GetDimension();
2984 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
2986 } else if (obj->InheritsFrom(TTree::Class())) {
2988 set = kTRUE;
2989 TString variables, cuts;
2991 fDim = 1;
2992 for ( int i = 0; i < variables.Length() && fDim <= 2; ++i )
2993 if ( ':' == variables[i] ) fDim += 1;
2994 // For any three of dimension bigger than 2, set the dimension
2995 // to 0, as we cannot infer the dimension from the TF1s, it's
2996 // better to have 0 as reference.
2997 if ( fDim > 2 ) fDim = 0;
2999 fMethodList->AddEntry("Unbinned Likelihood", kFP_MUBIN);
3001 } else if (obj->InheritsFrom(TH1::Class())){
3003 set = kTRUE;
3004 fDim = ((TH1*)obj)->GetDimension();
3006 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
3007 fMethodList->AddEntry("Binned Likelihood", kFP_MBINL);
3009 } else if (obj->InheritsFrom(TMultiGraph::Class())) {
3011 set = kTRUE;
3012 fDim = 1;
3014 fMethodList->AddEntry("Chi-square", kFP_MCHIS);
3017 fRobustValue->GetNumberEntry()->SetToolTipText("Set robust value");
3018 }
3019
3020 // Depending on the dimension of the object, allow the
3021 // visualization of sliders.
3022 if ( fDim < 2 || fType == kObjectTree )
3024 else
3026
3027 if ( fDim < 1 || fType == kObjectTree )
3029 else
3031
3032 // And also, depending on the dimension, add predefined functions.
3033 if ( fDim == 1 ) {
3034 if ( !fTypeFit->FindEntry("Predef-1D") )
3036 } else {
3037 if ( fTypeFit->FindEntry("Predef-1D") )
3039 }
3040
3041 if ( fDim == 2 ) {
3042 if ( !fTypeFit->FindEntry("Predef-2D") )
3044 } else {
3045 if ( fTypeFit->FindEntry("Predef-2D") )
3047 }
3048
3049 return set;
3050}
3051
3052////////////////////////////////////////////////////////////////////////////////
3053/// Show object name on the top.
3054
3056{
3057 TString name;
3058 bool isTree = false;
3059
3060 // Build the string to be compared to look for the object.
3061 if (obj) {
3062 name = obj->ClassName();
3063 name.Append("::");
3064 name.Append(obj->GetName());
3065 isTree = strcmp(obj->ClassName(), "TTree") == 0;
3066 } else {
3067 name = "No object selected";
3068 }
3069 fStatusBar->SetText(name.Data(),0);
3070
3071 // If the selection was done in the fDataSet combo box, there is no need
3072 // to search through the list
3073 TGTextLBEntry* selectedEntry = static_cast<TGTextLBEntry*> ( fDataSet->GetSelectedEntry());
3074 if ( selectedEntry ) {
3075 TString selectedName = selectedEntry->GetText()->GetString();
3076 if ( isTree )
3077 selectedName = selectedName(0, selectedName.First(' '));
3078 if ( name.CompareTo(selectedName) == 0 ) {
3079 Layout();
3080 return;
3081 }
3082 }
3083
3084 // Search through the list for the object
3085 Int_t entryId = kFP_NOSEL+1;
3086 bool found = false;
3087 while ( TGTextLBEntry* entry = static_cast<TGTextLBEntry*>
3088 ( fDataSet->GetListBox()->GetEntry(entryId)) ) {
3089 TString compareName = entry->GetText()->GetString();
3090 if ( isTree )
3091 compareName = compareName(0, compareName.First(' '));
3092 if ( name.CompareTo(compareName) == 0 ) {
3093 // If the object is found, select it
3094 fDataSet->Select(entryId, false);
3095 found = true;
3096 break;
3097 }
3098 entryId += 1;
3099 }
3100
3101 // If the object was not found, add it and select it.
3102 if ( !found ) {
3103 fDataSet->AddEntry(name.Data(), entryId);
3104 fDataSet->Select(entryId, kTRUE);
3105 }
3106
3107 Layout();
3108}
3109
3110////////////////////////////////////////////////////////////////////////////////
3111/// Get draw options of the selected object.
3112
3114{
3115 if (!fParentPad) return "";
3116
3118 TObject *obj;
3119 while ((obj = next())) {
3120 if (obj == fFitObject) return next.GetOption();
3121 }
3122 return "";
3123}
3124
3125////////////////////////////////////////////////////////////////////////////////
3126/// Set selected minimization library in use.
3127
3129{
3130 TGButton *bt = (TGButton *)gTQSender;
3131 Int_t id = bt->WidgetId();
3132
3133 switch (id) {
3134
3135 // Depending on the selected library, set the state of the rest
3136 // of the buttons.
3137 case kFP_LMIN:
3138 {
3139 if (on) {
3143 if ( fLibGSL->GetState() != kButtonDisabled )
3147 fStatusBar->SetText("LIB Minuit", 1);
3148 }
3149
3150 }
3151 break;
3152
3153 case kFP_LMIN2:
3154 {
3155 if (on) {
3159 if ( fLibGSL->GetState() != kButtonDisabled )
3163 fStatusBar->SetText("LIB Minuit2", 1);
3164 }
3165 }
3166 break;
3167
3168 case kFP_LFUM:
3169 {
3170 if (on) {
3174 if ( fLibGSL->GetState() != kButtonDisabled )
3178 fStatusBar->SetText("LIB Fumili", 1);
3179 }
3180 }
3181 break;
3182 case kFP_LGSL:
3183 {
3184 if (on) {
3188 if ( fLibGSL->GetState() != kButtonDisabled )
3192 fStatusBar->SetText("LIB GSL", 1);
3193 }
3194 }
3195 break;
3196 case kFP_LGAS:
3197 {
3198 if (on) {
3202 if ( fLibGSL->GetState() != kButtonDisabled )
3206 fStatusBar->SetText("LIB Genetics", 1);
3207 }
3208 }
3209 default:
3210 break;
3211 }
3213}
3214
3215////////////////////////////////////////////////////////////////////////////////
3216/// Set selected minimization method in use.
3217
3219{
3221 fStatusBar->SetText("MIGRAD",2);
3222 else if ( fMinMethodList->GetSelected() == kFP_FUMILI)
3223 fStatusBar->SetText("FUMILI",2);
3224 else if ( fMinMethodList->GetSelected() == kFP_SIMPLX )
3225 fStatusBar->SetText("SIMPLEX",2);
3226 else if ( fMinMethodList->GetSelected() == kFP_SCAN )
3227 fStatusBar->SetText("SCAN",2);
3229 fStatusBar->SetText("Combination",2);
3230 else if ( fMinMethodList->GetSelected() == kFP_GSLFR )
3231 fStatusBar->SetText("CONJFR",2);
3232 else if ( fMinMethodList->GetSelected() == kFP_GSLPR )
3233 fStatusBar->SetText("CONJPR",2);
3234 else if ( fMinMethodList->GetSelected() == kFP_BFGS )
3235 fStatusBar->SetText("BFGS",2);
3236 else if ( fMinMethodList->GetSelected() == kFP_BFGS2 )
3237 fStatusBar->SetText("BFGS2",2);
3238 else if ( fMinMethodList->GetSelected() == kFP_GSLLM )
3239 fStatusBar->SetText("GSLLM",2);
3240 else if ( fMinMethodList->GetSelected() == kFP_GSLSA)
3241 fStatusBar->SetText("SimAn",2);
3242 else if ( fMinMethodList->GetSelected() == kFP_TMVAGA )
3243 fStatusBar->SetText("TMVAGA",2);
3244 else if ( fMinMethodList->GetSelected() == kFP_GALIB )
3245 fStatusBar->SetText("GALIB",2);
3246
3247
3248}
3249
3250////////////////////////////////////////////////////////////////////////////////
3251/// Set the maximum number of iterations.
3252
3254{
3256 fStatusBar->SetText(Form("Itr: %ld",itr),2);
3257}
3258
3259////////////////////////////////////////////////////////////////////////////////
3260/// Create section title in the GUI.
3261
3262void TFitEditor::MakeTitle(TGCompositeFrame *parent, const char *title)
3263{
3264 TGCompositeFrame *ht = new TGCompositeFrame(parent, 350, 10,
3266 ht->AddFrame(new TGLabel(ht, title),
3267 new TGLayoutHints(kLHintsLeft, 1, 1, 0, 0));
3268 ht->AddFrame(new TGHorizontal3DLine(ht),
3269 new TGLayoutHints(kLHintsExpandX | kLHintsCenterY, 5, 5, 2, 2));
3270 parent->AddFrame(ht, new TGLayoutHints(kLHintsTop, 5, 0, 5, 0));
3271}
3272
3273////////////////////////////////////////////////////////////////////////////////
3274/// Look in the list of function for TF1. If a TF1 is
3275/// found in the list of functions, it will be returned
3276
3278{
3279 // Get the list of functions of the fit object
3281 TF1* func = 0;
3282
3283 // If it exists
3284 if ( lf ) {
3285 // Add the posibility to select previous fit function
3286 if ( !fTypeFit->FindEntry("Prev. Fit") )
3288
3289 // Then add all these functions to the fPrefFit structure.
3290 TObject *obj2;
3291 TIter next(lf, kIterForward);
3292 // Go over all the elements in lf
3293 while ((obj2 = next())) {
3294 if (obj2->InheritsFrom(TF1::Class())) {
3295 func = (TF1 *)obj2;
3296 fPrevFitIter it;
3297 // No go over all elements in fPrevFit
3298 for ( it = fPrevFit.begin(); it != fPrevFit.end(); ++it) {
3299 // To see wheather the object corresponds with fFitObject
3300 if ( it->first != fFitObject ) continue;
3301 // And if so, whether the function is already included
3302 if ( strcmp( func->GetName(), it->second->GetName() ) == 0 )
3303 break;
3304 if ( strcmp( func->GetName(), "PrevFitTMP" ) == 0 )
3305 break;
3306 }
3307 // Only if the function is not already in fPrevFit, the
3308 // breaks in the loops would make it to be different to
3309 // fPrevFit.end() if the function is already stored
3310 if ( it == fPrevFit.end() ) {
3311 fPrevFit.emplace(fFitObject, copyTF1(func));
3312 }
3313 }
3314 }
3315
3316 // Select the PrevFit set
3318 // And fill the function list
3321
3322
3323 } else {
3324 // If there is no prev fit functions.
3326 // Call FillFunctionList as it might happen that the user is
3327 // changing from a TTree to another one, and thus the fFuncList
3328 // if not properly filled
3330 }
3331
3333
3334 return func;
3335}
3336
3337////////////////////////////////////////////////////////////////////////////////
3338/// Retrieve the fitting options from all the widgets.
3339
3341{
3342 drawOpts = "";
3343
3344 fitOpts.Range = (fUseRange->GetState() == kButtonDown);
3345 fitOpts.Integral = (fIntegral->GetState() == kButtonDown);
3346 fitOpts.More = (fImproveResults->GetState() == kButtonDown);
3347 fitOpts.Errors = (fBestErrors->GetState() == kButtonDown);
3348 fitOpts.Like = (fMethodList->GetSelected() != kFP_MCHIS);
3349
3351 fitOpts.W1 = 2;
3352 else if (fAllWeights1->GetState() == kButtonDown)
3353 fitOpts.W1 = 1;
3354
3355 TString tmpStr = fEnteredFunc->GetText();
3356 if ( !(fLinearFit->GetState() == kButtonDown) &&
3357 (tmpStr.Contains("pol") || tmpStr.Contains("++")) )
3358 fitOpts.Minuit = 1;
3359
3360 // if ( (int) fFuncPars.size() == npar )
3361 // for ( Int_t i = 0; i < npar; ++i )
3362 // if ( fFuncPars[i][PAR_MIN] != fFuncPars[i][PAR_MAX] )
3363 //
3364
3365 // //fitOpts.Bound = 1;
3366 // break;
3367 // }
3368
3369 if (fChangedParams) {
3370 //std::cout << "Params have changed setting the Bound option " << std::endl;
3371 fitOpts.Bound = 1;
3372 fChangedParams = kFALSE; // reset
3373 }
3374
3375 //fitOpts.Nochisq = (fNoChi2->GetState() == kButtonDown);
3376 fitOpts.Nostore = (fNoStoreDrawing->GetState() == kButtonDown);
3377 fitOpts.Nograph = (fNoDrawing->GetState() == kButtonDown);
3378 fitOpts.Plus = (fAdd2FuncList->GetState() == kButtonDown);
3379 fitOpts.Gradient = (fUseGradient->GetState() == kButtonDown);
3380 fitOpts.Quiet = ( fOptQuiet->GetState() == kButtonDown );
3381 fitOpts.Verbose = ( fOptVerbose->GetState() == kButtonDown );
3382
3383 if ( !(fType != kObjectGraph) && (fEnableRobust->GetState() == kButtonDown) )
3384 {
3385 fitOpts.Robust = 1;
3386 fitOpts.hRobust = fRobustValue->GetNumber();
3387 }
3388
3389 drawOpts = GetDrawOption();
3390
3391 if ( fLibMinuit->GetState() == kButtonDown )
3392 minOpts.SetMinimizerType ( "Minuit");
3393 else if ( fLibMinuit2->GetState() == kButtonDown)
3394 minOpts.SetMinimizerType ( "Minuit2" );
3395 else if ( fLibFumili->GetState() == kButtonDown )
3396 minOpts.SetMinimizerType ("Fumili" );
3397 else if ( fLibGSL->GetState() == kButtonDown )
3398 minOpts.SetMinimizerType ("GSLMultiMin" );
3399
3401 minOpts.SetMinimizerAlgorithm( "Migrad" );
3402 else if ( fMinMethodList->GetSelected() == kFP_FUMILI)
3403 if ( fLibMinuit2->GetState() == kButtonDown )
3404 minOpts.SetMinimizerAlgorithm( "Fumili2" );
3405 else
3406 minOpts.SetMinimizerAlgorithm( "Fumili" );
3407 else if ( fMinMethodList->GetSelected() == kFP_SIMPLX )
3408 minOpts.SetMinimizerAlgorithm( "Simplex" );
3409 else if ( fMinMethodList->GetSelected() == kFP_SCAN )
3410 minOpts.SetMinimizerAlgorithm( "Scan" );
3412 minOpts.SetMinimizerAlgorithm( "Minimize" );
3413 else if ( fMinMethodList->GetSelected() == kFP_GSLFR )
3414 minOpts.SetMinimizerAlgorithm( "conjugatefr" );
3415 else if ( fMinMethodList->GetSelected() == kFP_GSLPR )
3416 minOpts.SetMinimizerAlgorithm( "conjugatepr" );
3417 else if ( fMinMethodList->GetSelected() == kFP_BFGS )
3418 minOpts.SetMinimizerAlgorithm( "bfgs" );
3419 else if ( fMinMethodList->GetSelected() == kFP_BFGS2 )
3420 minOpts.SetMinimizerAlgorithm( "bfgs2" );
3421 else if ( fMinMethodList->GetSelected() == kFP_GSLLM ) {
3422 minOpts.SetMinimizerType ("GSLMultiFit" );
3423 minOpts.SetMinimizerAlgorithm( "" );
3424 } else if ( fMinMethodList->GetSelected() == kFP_GSLSA) {
3425 minOpts.SetMinimizerType ("GSLSimAn" );
3426 minOpts.SetMinimizerAlgorithm( "" );
3427 } else if ( fMinMethodList->GetSelected() == kFP_TMVAGA) {
3428 minOpts.SetMinimizerType ("Geneti2c" );
3429 minOpts.SetMinimizerAlgorithm( "" );
3430 } else if ( fMinMethodList->GetSelected() == kFP_GALIB) {
3431 minOpts.SetMinimizerType ("GAlibMin" );
3432 minOpts.SetMinimizerAlgorithm( "" );
3433 }
3434
3435 minOpts.SetErrorDef ( fErrorScale->GetNumber() );
3436 minOpts.SetTolerance( fTolerance->GetNumber() );
3439}
3440
3442{
3443 // Set the state of some input widgets depending on whether the fit
3444 // function can be defined by text or if it is an existing one.
3445 if ( state )
3446 {
3447 fEnteredFunc-> SetState(kTRUE);
3448 fAdd -> SetState(kButtonUp, kFALSE);
3449 fNormAdd -> SetState(kButtonUp, kFALSE);
3450 fConv -> SetState(kButtonUp, kFALSE);
3451 fNone -> SetState(kButtonDown,kFALSE); // fNone::State is the one used as reference
3452 }
3453 else
3454 {
3455 fEnteredFunc-> SetState(kFALSE);
3456 fAdd -> SetState(kButtonDisabled, kFALSE);
3457 fNormAdd -> SetState(kButtonDisabled, kFALSE);
3458 fConv -> SetState(kButtonDisabled, kFALSE);
3459 fNone -> SetState(kButtonDisabled, kFALSE);
3460 }
3461}
3462
3464{
3465 // Return the ranges selected by the sliders.
3466
3467 // It's not working for trees as they don't have TAxis.
3468 if ( fType == kObjectTree ) return;
3469
3470 if ( fType != kObjectTree ) {
3471 Int_t ixmin = (Int_t)(fSliderX->GetMinPosition());
3472 Int_t ixmax = (Int_t)(fSliderX->GetMaxPosition());
3474 Double_t xmax = fXaxis->GetBinUpEdge(ixmax);
3475 drange.AddRange(0,xmin, xmax);
3476 }
3477
3478 if ( fDim > 1 ) {
3479 assert(fYaxis);
3480 Int_t iymin = (Int_t)(fSliderY->GetMinPosition());
3481 Int_t iymax = (Int_t)(fSliderY->GetMaxPosition());
3483 Double_t ymax = fYaxis->GetBinUpEdge(iymax);
3484 drange.AddRange(1,ymin, ymax);
3485 }
3486 if ( fDim > 2 ) {
3487 assert(fZaxis);
3488 Int_t izmin = (Int_t)(fSliderZ->GetMinPosition());
3489 Int_t izmax = (Int_t)(fSliderZ->GetMaxPosition());
3490 Double_t zmin = fZaxis->GetBinLowEdge(izmin);
3491 Double_t zmax = fZaxis->GetBinUpEdge(izmax);
3492 drange.AddRange(2,zmin, zmax);
3493 }
3494}
3495
3497{
3498 // Get the list of functions previously used in the fitobject.
3499
3500 TList *listOfFunctions = 0;
3501 if ( fFitObject ) {
3502 switch (fType) {
3503
3504 case kObjectHisto:
3505 listOfFunctions = ((TH1 *)fFitObject)->GetListOfFunctions();
3506 break;
3507
3508 case kObjectGraph:
3509 listOfFunctions = ((TGraph *)fFitObject)->GetListOfFunctions();
3510 break;
3511
3512 case kObjectMultiGraph:
3513 listOfFunctions = ((TMultiGraph *)fFitObject)->GetListOfFunctions();
3514 break;
3515
3516 case kObjectGraph2D:
3517 listOfFunctions = ((TGraph2D *)fFitObject)->GetListOfFunctions();
3518 break;
3519
3520 case kObjectHStack:
3521 case kObjectTree:
3522 default:
3523 break;
3524 }
3525 }
3526 return listOfFunctions;
3527}
3528
3530{
3531 // Looks for all the functions registered in the current ROOT
3532 // session.
3533
3534 // First, clean the copies stored in fSystemFunc
3535 for (auto func : fSystemFuncs)
3536 delete func;
3537
3538 fSystemFuncs.clear();
3539
3540 // Be carefull not to store functions that will be in the
3541 // predefined section
3542 const unsigned int nfuncs = 16;
3543 const char* fnames[nfuncs] = { "gaus" , "gausn", "expo", "landau",
3544 "landaun", "pol0", "pol1", "pol2",
3545 "pol3", "pol4", "pol5", "pol6",
3546 "pol7", "pol8", "pol9", "user"
3547 };
3548
3549 // No go through all the objects registered in gROOT
3550 TIter functionsIter(gROOT->GetListOfFunctions());
3551 TObject* obj;
3552 while( ( obj = (TObject*) functionsIter() ) ) {
3553 // And if they are TF1s
3554 if ( TF1* func = dynamic_cast<TF1*>(obj) ) {
3555 bool addFunction = true;
3556 // And they are not already registered in fSystemFunc
3557 for ( unsigned int i = 0; i < nfuncs; ++i ) {
3558 if ( strcmp( func->GetName(), fnames[i] ) == 0 ) {
3559 addFunction = false;
3560 break;
3561 }
3562 }
3563 // Add them.
3564 if ( addFunction )
3565 fSystemFuncs.emplace_back( copyTF1(func) );
3566 }
3567 }
3568}
3569
3571{
3572 // This function returns a TList with all the functions used in the
3573 // FitPanel to fit a given object. If the object passed is NULL,
3574 // then the object used is the currently selected one. It is
3575 // important to notice that the FitPanel is still the owner of
3576 // those functions. This means that the user SHOULD NOT delete any
3577 // of these functions, as the FitPanel will do so in the
3578 // destructor.
3579
3580 if (!obj) obj = fFitObject;
3581
3582 TList *retList = new TList();
3583
3584 std::pair<fPrevFitIter, fPrevFitIter> look = fPrevFit.equal_range(obj);
3585 for ( fPrevFitIter it = look.first; it != look.second; ++it ) {
3586 retList->Add(it->second);
3587 }
3588
3589 return retList;
3590}
3591
3593{
3594 // Get the fit function selected or declared in the fiteditor
3595
3596 TF1 *fitFunc = 0;
3597 // If the function is not editable ==> it means it is registered in
3598 // gROOT
3599 if ( fNone->GetState() == kButtonDisabled )
3600 {
3601 // So we find it
3602 TF1* tmpF1 = FindFunction();
3603 // And if we don't find it, then it means there is something wrong!
3604 if ( tmpF1 == 0 )
3605 {
3607 "Error...", "1) Verify the entered function string!",
3608 kMBIconStop,kMBOk, 0);
3609 return 0;
3610 }
3611
3612 // Now we make a copy that will be used temporary. The caller of
3613 // the function should delete the returned function.
3614 fitFunc = (TF1*)tmpF1->IsA()->New();
3615 tmpF1->Copy(*fitFunc);
3616 // Copy the parameters of the function, if and only if the
3617 // parameters stored does not correspond with the ones of these
3618 // functions. Perhaps the user has already called
3619 // DoSetParameters. There is no way to know whether the
3620 // parameters have been modified, so we check the size of
3621 // fFuncPars against number of parameters.
3622 if ( int(fFuncPars.size()) != tmpF1->GetNpar() )
3623 {
3624 fitFunc->SetParameters(tmpF1->GetParameters());
3625 GetParameters(fFuncPars, fitFunc);
3626 } else {
3627 SetParameters(fFuncPars, fitFunc);
3628 }
3629 }
3630
3631 // If, we have no function at this point, it means that is is
3632 // described in fEnteredFunc, so we create it from scratch.
3633 if ( fitFunc == 0 )
3634 {
3635 ROOT::Fit::DataRange drange;
3636 GetRanges(drange);
3637 double xmin, xmax, ymin, ymax, zmin, zmax;
3638 drange.GetRange(xmin, xmax, ymin, ymax, zmin, zmax);
3639
3640 // Depending of course on the number of dimensions the object
3641 // has. These commands will raise an error message if the user
3642 // has not defined the function properly
3643 if ( fDim == 1 || fDim == 0 )
3644 {
3645
3646 fitFunc = new TF1("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax );
3647 //std::cout << "GetFitFunction - created function PrevFitTMP " << fEnteredFunc->GetText() << " " << fitFunc << std::endl;
3648 if (fNormAdd->IsOn())
3649 {
3650 if (fSumFunc) delete fSumFunc;
3652 fitFunc = new TF1("PrevFitTMP", *fSumFunc, xmin, xmax, fSumFunc->GetNpar());
3653 for (int i = 0; i < fitFunc->GetNpar(); ++i) fitFunc->SetParName(i, fSumFunc->GetParName(i) );
3654 //std::cout << "create fit normalized function " << fSumFunc << " fitfunc " << fitFunc << std::endl;
3655 }
3656
3657 if (fConv -> IsOn())
3658 {
3659 if (fConvFunc) delete fConvFunc;
3661 fitFunc = new TF1("PrevFitTMP", *fConvFunc, xmin, xmax, fConvFunc->GetNpar());
3662 for (int i = 0; i < fitFunc->GetNpar(); ++i) fitFunc->SetParName(i, fConvFunc->GetParName(i) );
3663 //std::cout << "create fit convolution function " << fSumFunc << " fitfunc " << fitFunc << std::endl;
3664 }
3665 }
3666 else if ( fDim == 2 ) {
3667 fitFunc = new TF2("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax, ymin, ymax );
3668 }
3669 else if ( fDim == 3 ) {
3670 fitFunc = new TF3("PrevFitTMP",fEnteredFunc->GetText(), xmin, xmax, ymin, ymax, zmin, zmax );
3671 }
3672
3673 // if the function is not a C defined
3674 if ( fNone->GetState() != kButtonDisabled )
3675 {
3676 // and the formulas are the same
3677 TF1* tmpF1 = FindFunction();
3678// if (tmpF1)
3679 //std::cout << "GetFitFunction: found existing function " << tmpF1 << " " << tmpF1->GetName() << " " << tmpF1->GetExpFormula() << std::endl;
3680// else
3681 //std::cout << "GetFitFunction: - no existing function found " << std::endl;
3682 if ( tmpF1 != 0 && fitFunc != 0 &&
3683 strcmp(tmpF1->GetExpFormula(), fEnteredFunc->GetText()) == 0 ) {
3684 // copy everything from the founction available in gROOT
3685 //std::cout << "GetFitFunction: copying tmp function in PrevFitTMP " << tmpF1->GetName() << " "
3686 // << tmpF1->GetExpFormula() << std::endl;
3687 tmpF1->Copy(*fitFunc);
3688 if ( int(fFuncPars.size()) != tmpF1->GetNpar() )
3689 {
3690 GetParameters(fFuncPars, fitFunc);
3691 }
3692 }
3693 }
3694 }
3695
3696 return fitFunc;
3697}
@ kButton1Down
Definition: Buttons.h:17
@ kWatch
Definition: GuiTypes.h:375
@ kPointer
Definition: GuiTypes.h:375
@ 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
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
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
unsigned int UInt_t
Definition: RtypesCore.h:46
float Float_t
Definition: RtypesCore.h:57
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:375
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
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:46
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition: TString.cxx:2456
#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:293
const double * Coords(unsigned int ipoint) const
return a pointer to the coordinates data for the given fit point
Definition: FitData.h:236
Class describing the un-binned data sets (just x coordinates values) of any dimensions.
Definition: UnBinData.h:46
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:1203
Int_t GetWindowTopY()
Returns current top y position of window on screen.
Definition: TCanvas.cxx:1214
virtual void Selected(TVirtualPad *pad, TObject *obj, Int_t event)
Emit Selected() signal.
Definition: TCanvas.cxx:1631
void SetCursor(ECursor cursor) override
Set cursor.
Definition: TCanvas.cxx:1989
UInt_t GetWindowWidth() const
Definition: TCanvas.h:160
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4967
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:361
1-Dim function class
Definition: TF1.h:213
virtual Int_t GetNumber() const
Definition: TF1.h:503
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition: TF1.cxx:1956
static TClass * Class()
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition: TF1.cxx:3566
virtual Int_t GetNpar() const
Definition: TF1.h:486
virtual TString GetExpFormula(Option_t *option="") const
Definition: TF1.h:466
virtual void SetParent(TObject *p=nullptr)
Definition: TF1.h:670
virtual Double_t * GetParameters() const
Definition: TF1.h:525
void Copy(TObject &f1) const override
Copy this F1 to a new F1.
Definition: TF1.cxx:1015
void Draw(Option_t *option="") override
Draw this function with its current attributes.
Definition: TF1.cxx:1343
virtual void GetRange(Double_t *xmin, Double_t *xmax) const
Return range of a generic N-D function.
Definition: TF1.cxx:2295
virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
Set lower and upper limits for parameter ipar.
Definition: TF1.cxx:3545
virtual void SetParName(Int