Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFitPanel.cxx
Go to the documentation of this file.
1// Authors: Sergey Linev <S.Linev@gsi.de> Iliana Betsou <Iliana.Betsou@cern.ch>
2// Date: 2019-04-11
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include <ROOT/RFitPanel.hxx>
14
15#include <ROOT/RLogger.hxx>
16
17#include "Fit/BinData.h"
18#include "Fit/Fitter.h"
19
20#include "TString.h"
21#include "TGraph.h"
22#include "TGraphErrors.h"
23#include "TGraph2D.h"
24#include "TGraph2DErrors.h"
25#include "TMultiGraph.h"
26#include "THStack.h"
27#include "TROOT.h"
28#include "TH1.h"
29#include "TH2.h"
30#include "TF1.h"
31#include "TF2.h"
32#include "TF3.h"
33#include "TFitResult.h"
34#include "TList.h"
35#include "TVirtualPad.h"
36#include "TCanvas.h"
37#include "TDirectory.h"
38#include "TBufferJSON.h"
39#include "Math/Minimizer.h"
40#include "HFitInterface.h"
41#include "TColor.h"
42
43#include <iostream>
44#include <iomanip>
45#include <memory>
46#include <sstream>
47
48using namespace std::string_literals;
49
50/** \class ROOT::Experimental::RFitPanel
51\ingroup webwidgets
52
53web-based FitPanel prototype.
54*/
55
56////////////////////////////////////////////////////////////////////////////////
57/// Constructor
58
59ROOT::Experimental::RFitPanel::FitRes::FitRes(const std::string &_objid, std::unique_ptr<TF1> &_func, TFitResultPtr &_res)
60 : objid(_objid), res(_res)
61{
62 std::swap(func, _func);
63}
64
65////////////////////////////////////////////////////////////////////////////////
66/// Destructor
67
69{
70 // to avoid dependency from TF1
71}
72
73////////////////////////////////////////////////////////////////////////////////
74/// Constructor
75
77{
78 model().fTitle = title;
79
81}
82
83////////////////////////////////////////////////////////////////////////////////
84/// Destructor
85
87{
88 // to avoid dependency from TF1
89}
90
91////////////////////////////////////////////////////////////////////////////////
92/// Returns RWebWindow instance, used to display FitPanel
93
94std::shared_ptr<ROOT::Experimental::RWebWindow> ROOT::Experimental::RFitPanel::GetWindow()
95{
96 if (!fWindow) {
98
99 fWindow->SetPanelName("rootui5.fitpanel.view.FitPanel");
100
101 fWindow->SetCallBacks(
102 [this](unsigned connid)
103 {
104 fConnId = connid;
105 fWindow->Send(fConnId, "INITDONE");
106 if (!model().fInitialized)
107 SelectObject("$$$");
108 SendModel();
109 },
110 [this](unsigned connid, const std::string &arg) { ProcessData(connid, arg); },
111 [this](unsigned) { fConnId = 0; });
112
113 fWindow->SetGeometry(400, 650); // configure predefined geometry
114 }
115
116 return fWindow;
117}
118
119////////////////////////////////////////////////////////////////////////////////
120/// Update list of available data
121
123{
124 auto &m = model();
125
126 m.fDataSet.clear();
127
128 for (auto &obj : fObjects)
129 m.fDataSet.emplace_back("Panel", "panel::"s + obj->GetName(), Form("%s::%s", obj->ClassName(), obj->GetName()));
130
131 if (gDirectory) {
132 TIter iter(gDirectory->GetList());
133 TObject *obj = nullptr;
134 while ((obj = iter()) != nullptr) {
136 m.fDataSet.emplace_back("gDirectory", "gdir::"s + obj->GetName(), Form("%s::%s", obj->ClassName(), obj->GetName()));
137 }
138 }
139}
140
141////////////////////////////////////////////////////////////////////////////////
142/// Select object for fitting
143
145{
147
148 auto &m = model();
149
150 std::string id = objid;
151 if (id.compare("$$$") == 0) {
152 if (m.fDataSet.size() > 0)
153 id = m.fDataSet[0].id;
154 else
155 id.clear();
156 }
157
158 TObject *obj = GetSelectedObject(id);
159 auto kind = GetFitObjectType(obj);
160
161 m.SetObjectKind(kind);
162
163 TH1 *hist = nullptr;
164 switch (kind) {
166 hist = (TH1*)obj;
167 break;
168
170 hist = ((TGraph*)obj)->GetHistogram();
171 break;
172
174 hist = ((TMultiGraph*)obj)->GetHistogram();
175 break;
176
178 hist = ((TGraph2D*)obj)->GetHistogram("empty");
179 break;
180
182 hist = (TH1 *)((THStack *)obj)->GetHists()->First();
183 break;
184
185 //case RFitPanelModel::kObjectTree:
186 // m.fFitMethods = {{ kFP_MUBIN, "Unbinned Likelihood" }};
187 // m.fFitMethod = kFP_MUBIN;
188 // break;
189
190 default:
191 break;
192 }
193
194 if (!obj)
195 m.fSelectedData = "";
196 else
197 m.fSelectedData = id;
198
199 m.fInitialized = true;
200
201 // update list of data
202
203 m.UpdateRange(hist);
204
206
207 std::string selfunc = m.fSelectedFunc;
208
209 if (!m.HasFunction(selfunc)) {
210 if (m.fFuncList.size() > 0)
211 selfunc = m.fFuncList[0].id;
212 else
213 selfunc.clear();
214 }
215
216 SelectFunction(selfunc);
217}
218
219////////////////////////////////////////////////////////////////////////////////
220/// Returns object based on it string id
221/// Searches either in gDirectory or in internal panel list
222
224{
225 if (objid.compare(0,6,"gdir::") == 0) {
226 std::string name = objid.substr(6);
227 if (gDirectory)
228 return gDirectory->GetList()->FindObject(name.c_str());
229 } else if (objid.compare(0,7,"panel::") == 0) {
230 std::string name = objid.substr(7);
231 for (auto &item : fObjects)
232 if (name.compare(item->GetName()) == 0)
233 return item;
234 }
235
236 return nullptr;
237}
238
239////////////////////////////////////////////////////////////////////////////////
240/// Returns kind of object
241
243{
244 if (!obj)
246
247 if (obj->InheritsFrom(TH1::Class()))
249
250 if (obj->InheritsFrom(TGraph::Class()))
252
253 if (obj->InheritsFrom(TGraph2D::Class()))
255
256 if (obj->InheritsFrom(THStack::Class()))
258
259 if (obj->InheritsFrom(TMultiGraph::Class()))
261
263}
264
265////////////////////////////////////////////////////////////////////////////////
266/// Update list of available functions
267
269{
270 auto &m = model();
271
272 m.fFuncList.clear();
273
274 if (m.fDim == 1) {
275 m.fFuncList = { {"gaus"}, {"gausn"}, {"expo"}, {"landau"}, {"landaun"},
276 {"pol0"},{"pol1"},{"pol2"},{"pol3"},{"pol4"},{"pol5"},{"pol6"},{"pol7"},{"pol8"},{"pol9"},
277 {"cheb0"}, {"cheb1"}, {"cheb2"}, {"cheb3"}, {"cheb4"}, {"cheb5"}, {"cheb6"}, {"cheb7"}, {"cheb8"}, {"cheb9"} };
278 } else if (m.fDim == 2) {
279 m.fFuncList = { {"xygaus"}, {"bigaus"}, {"xyexpo"}, {"xylandau"}, {"xylandaun"} };
280 }
281
282 for (auto &func : fSystemFuncs) {
283 m.fFuncList.emplace_back("System", "system::"s + func->GetName(), func->GetName());
284 }
285
286 for (auto &entry : fPrevRes) {
287 if (entry.objid == m.fSelectedData)
288 m.fFuncList.emplace_back("Previous", "previous::"s + entry.func->GetName(), entry.func->GetName());
289 }
290}
291
292////////////////////////////////////////////////////////////////////////////////
293/// Select fit function
294
296{
297 model().SelectedFunc(funcid, FindFunction(funcid));
298
300}
301
302////////////////////////////////////////////////////////////////////////////////
303/// Assign histogram to use with fit panel - without ownership
304
306{
307 fObjects.emplace_back(hist);
308 SelectObject("panel::"s + hist->GetName());
309 SendModel();
310}
311
312/// Assign histogram name to use with fit panel - it should be available in gDirectory
313
315{
316 SelectObject("gdir::" + hname);
317 SendModel();
318}
319
320////////////////////////////////////////////////////////////////////////////////
321/// assign canvas to use for drawing results of fitting or showing fitpanel itself
322
323void ROOT::Experimental::RFitPanel::AssignCanvas(std::shared_ptr<RCanvas> &canv)
324{
325 if (!fCanvas) {
326 fCanvas = canv;
327 } else {
328 R__LOG_ERROR(FitPanelLog()) << "FitPanel already bound to the canvas - change is not yet supported";
329 }
330}
331
332////////////////////////////////////////////////////////////////////////////////
333/// assign histogram for fitting
334
335void ROOT::Experimental::RFitPanel::AssignHistogram(std::shared_ptr<RH1D> &hist)
336{
337 fFitHist = hist;
338}
339
340////////////////////////////////////////////////////////////////////////////////
341/// Show FitPanel
342
343void ROOT::Experimental::RFitPanel::Show(const std::string &where)
344{
345 GetWindow()->Show(where);
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Hide FitPanel
350
352{
353 if (fWindow)
354 fWindow->CloseConnections();
355}
356
357////////////////////////////////////////////////////////////////////////////////
358/// Return reference on model object
359/// Model created if was not exists before
360
361
363{
364 if (!fModel) {
365 fModel = std::make_unique<RFitPanelModel>();
366 fModel->Initialize();
367 }
368
369 return *fModel.get();
370}
371
372////////////////////////////////////////////////////////////////////////////////
373/// Send model object to the client
374
376{
377 if (fWindow && (fConnId > 0)) {
379 fWindow->Send(fConnId, "MODEL:"s + json.Data());
380 }
381}
382
383////////////////////////////////////////////////////////////////////////////////
384/// Process data from FitPanel
385/// OpenUI5-based FitPanel sends commands or status changes
386
387void ROOT::Experimental::RFitPanel::ProcessData(unsigned, const std::string &arg)
388{
389 if (arg == "RELOAD") {
390
392
395
396 SendModel();
397
398 } else if (arg.compare(0, 7, "UPDATE:") == 0) {
399
400 if (UpdateModel(arg.substr(7)) > 0)
401 SendModel();
402
403 } else if (arg.compare(0, 6, "DOFIT:") == 0) {
404
405 if (UpdateModel(arg.substr(6)) >= 0)
406 if (DoFit())
407 SendModel();
408
409 } else if (arg.compare(0, 7, "DODRAW:") == 0) {
410
411 if (UpdateModel(arg.substr(7)) >= 0)
412 if (DoDraw())
413 SendModel();
414
415 } else if (arg.compare(0, 8, "SETPARS:") == 0) {
416
417 auto info = TBufferJSON::FromJSON<RFitPanelModel::RFuncParsList>(arg.substr(8));
418
419 if (info) {
420 TF1 *func = FindFunction(info->id);
421
422 // copy all parameters back to the function
423 if (func)
424 info->SetParameters(func);
425 }
426
427 }
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// Search for existing functions, ownership still belongs to FitPanel or global lists
432
434{
435 if (id.compare(0,8,"system::") == 0) {
436 std::string name = id.substr(8);
437
438 for (auto &item : fSystemFuncs)
439 if (name.compare(item->GetName()) == 0)
440 return item.get();
441 }
442
443 if (id.compare(0,10,"previous::") == 0) {
444 std::string name = id.substr(10);
445
446 for (auto &entry : fPrevRes)
447 if (name.compare(entry.func->GetName()) == 0)
448 return entry.func.get();
449 }
450
451 return nullptr;
452}
453
454////////////////////////////////////////////////////////////////////////////////
455/// Creates new instance to make fitting
456
458{
459 if (id.compare(0,10,"previous::") == 0) {
460 std::string name = id.substr(10);
461
462 for (auto &entry : fPrevRes)
463 if (name.compare(entry.func->GetName()) == 0)
464 return entry.res.Get();
465 }
466
467 return nullptr;
468}
469
470////////////////////////////////////////////////////////////////////////////////
471/// Creates new instance to make fitting
472
473std::unique_ptr<TF1> ROOT::Experimental::RFitPanel::GetFitFunction(const std::string &funcname)
474{
475 std::unique_ptr<TF1> res;
476
477 TF1 *func = FindFunction(funcname);
478
479 if (func) {
480 // Now we make a copy.
481 res.reset((TF1*) func->IsA()->New());
482 func->Copy(*res);
483 } else if (funcname.compare(0,6,"dflt::") == 0) {
484
485 std::string formula = funcname.substr(6);
486
488
489 double xmin, xmax, ymin, ymax, zmin, zmax;
490 drange.GetRange(xmin, xmax, ymin, ymax, zmin, zmax);
491
492 if ( model().fDim == 1 || model().fDim == 0 ) {
493 res.reset(new TF1(formula.c_str(), formula.c_str(), xmin, xmax));
494 } else if ( model().fDim == 2 ) {
495 res.reset(new TF2(formula.c_str(), formula.c_str(), xmin, xmax, ymin, ymax));
496 } else if ( model().fDim == 3 ) {
497 res.reset(new TF3(formula.c_str(), formula.c_str(), xmin, xmax, ymin, ymax, zmin, zmax));
498 }
499 }
500
501 return res;
502}
503
504////////////////////////////////////////////////////////////////////////////////
505/// Update fit model
506/// returns -1 if JSON fails
507/// return 0 if nothing large changed
508/// return 1 if important selection are changed and client need to be updated
509
511{
512 auto m = TBufferJSON::FromJSON<RFitPanelModel>(json);
513
514 if (!m) {
515 R__LOG_ERROR(FitPanelLog()) << "Fail to parse JSON for RFitPanelModel";
516 return -1;
517 }
518
519 m->fInitialized = true;
520
521 int res = 0; // nothing changed
522
523 if (model().fSelectedData != m->fSelectedData) {
524 res |= 1;
525 }
526
527 if (model().fSelectedFunc != m->fSelectedFunc) {
528 res |= 2;
529 }
530
531 std::swap(fModel, m); // finally replace model
532
533 if (res & 1)
534 SelectObject(model().fSelectedData);
535
536 if (res != 0)
537 SelectFunction(model().fSelectedFunc);
538
539 return res;
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// Copies f into a new TF1 to be stored in the fitpanel with it's
544/// own ownership. This is taken from Fit::StoreAndDrawFitFunction in
545/// HFitImpl.cxx
546
548{
549 double xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;
550
551 // no need to use kNotGlobal bit. TF1::Copy does not add in the list by default
552 if ( dynamic_cast<TF3*>(f)) {
553 TF3* fnew = (TF3*)f->IsA()->New();
554 f->Copy(*fnew);
555 f->GetRange(xmin,ymin,zmin,xmax,ymax,zmax);
556 fnew->SetRange(xmin,ymin,zmin,xmax,ymax,zmax);
557 fnew->SetParent( nullptr );
558 fnew->AddToGlobalList(false);
559 return fnew;
560 } else if ( dynamic_cast<TF2*>(f) != 0 ) {
561 TF2* fnew = (TF2*)f->IsA()->New();
562 f->Copy(*fnew);
563 f->GetRange(xmin,ymin,xmax,ymax);
564 fnew->SetRange(xmin,ymin,xmax,ymax);
565 fnew->Save(xmin,xmax,ymin,ymax,0,0);
566 fnew->SetParent( nullptr );
567 fnew->AddToGlobalList(false);
568 return fnew;
569 }
570
571 TF1* fnew = (TF1*)f->IsA()->New();
572 f->Copy(*fnew);
573 f->GetRange(xmin,xmax);
574 fnew->SetRange(xmin,xmax);
575 // This next line is added, as fnew-Save fails with gausND! As
576 // the number of dimensions is unknown...
577 if ( '\0' != fnew->GetExpFormula()[0] )
578 fnew->Save(xmin,xmax,0,0,0,0);
579 fnew->SetParent( nullptr );
580 fnew->AddToGlobalList(false);
581 return fnew;
582}
583
584////////////////////////////////////////////////////////////////////////////////
585/// Looks for all the functions registered in the current ROOT
586/// session.
587
589{
590
591 fSystemFuncs.clear();
592
593 // Be carefull not to store functions that will be in the
594 // predefined section
595 std::vector<std::string> fnames = { "gaus" , "gausn", "expo", "landau",
596 "landaun", "pol0", "pol1", "pol2",
597 "pol3", "pol4", "pol5", "pol6",
598 "pol7", "pol8", "pol9", "user" };
599
600 // No go through all the objects registered in gROOT
601 TIter functionsIter(gROOT->GetListOfFunctions());
602 TObject* obj;
603 while( (obj = functionsIter()) != nullptr ) {
604 // And if they are TF1s
605 if ( TF1* func = dynamic_cast<TF1*>(obj) ) {
606 bool addFunction = true;
607 // And they are not already registered in fSystemFunc
608 for ( auto &name : fnames) {
609 if ( name.compare(func->GetName()) == 0 ) {
610 addFunction = false;
611 break;
612 }
613 }
614 // Add them.
615 if ( addFunction )
616 fSystemFuncs.emplace_back( copyTF1(func) );
617 }
618 }
619}
620
621////////////////////////////////////////////////////////////////////////////////
622/// Returns pad where histogram is drawn
623/// If canvas not exists, create new one
624
626{
627 if (!obj || (!force && (model().fNoDrawing || model().fNoStoreDraw)))
628 return nullptr;
629
630 std::function<TPad*(TPad*)> check = [&](TPad *pad) {
631 TPad *res = nullptr;
632 if (!pad) return res;
633 if (!fPadName.empty() && (fPadName.compare(pad->GetName()) == 0)) return pad;
634 TIter next(pad->GetListOfPrimitives());
635 TObject *prim = nullptr;
636 while (!res && (prim = next())) {
637 res = (prim == obj) ? pad : check(dynamic_cast<TPad *>(prim));
638 }
639 return res;
640 };
641
642 if (!fCanvName.empty()) {
643 auto drawcanv = dynamic_cast<TCanvas *> (gROOT->GetListOfCanvases()->FindObject(fCanvName.c_str()));
644 auto drawpad = check(drawcanv);
645 if (drawpad) {
646 drawpad->cd();
647 return drawpad;
648 }
649 if (drawcanv) {
650 drawcanv->Clear();
651 drawcanv->cd();
652 obj->Draw();
653 return drawcanv;
654 }
655 fCanvName.clear();
656 fPadName.clear();
657 }
658
659 TObject *c = nullptr;
660 TIter nextc(gROOT->GetListOfCanvases());
661 while ((c = nextc())) {
662 auto drawpad = check(dynamic_cast<TCanvas* >(c));
663 if (drawpad) {
664 drawpad->cd();
665 fCanvName = c->GetName();
666 fPadName = drawpad->GetName();
667 return drawpad;
668 }
669 }
670
671 auto canv = gROOT->MakeDefCanvas();
672 canv->SetName("fpc");
673 canv->SetTitle("Fit panel drawings");
674 fPadName = fCanvName = canv->GetName();
675
676 canv->cd();
677 obj->Draw();
678
679 return canv;
680}
681
682////////////////////////////////////////////////////////////////////////////////
683/// Perform fitting using current model settings
684/// Returns true if any action was done
685
687{
688 auto &m = model();
689
690 TObject *obj = GetSelectedObject(m.fSelectedData);
691 if (!obj) return false;
692 auto kind = GetFitObjectType(obj);
693
694 auto f1 = GetFitFunction(m.fSelectedFunc);
695 if (!f1) return false;
696
697 auto drange = m.GetRanges();
698 auto minOption = m.GetMinimizerOptions();
699 auto fitOpts = m.GetFitOptions();
700 auto drawOpts = m.GetDrawOption();
701
702 fitOpts.StoreResult = 1;
703
704 TVirtualPad *save = gPad;
705
706 auto pad = GetDrawPad(obj);
707
708 TFitResultPtr res;
709
710 switch (kind) {
712
713 TH1 *hist = dynamic_cast<TH1*>(obj);
714 if (hist)
715 res = ROOT::Fit::FitObject(hist, f1.get(), fitOpts, minOption, drawOpts, drange);
716
717 break;
718 }
720
721 TGraph *gr = dynamic_cast<TGraph*>(obj);
722 if (gr)
723 res = ROOT::Fit::FitObject(gr, f1.get(), fitOpts, minOption, drawOpts, drange);
724 break;
725 }
727
728 TMultiGraph *mg = dynamic_cast<TMultiGraph*>(obj);
729 if (mg)
730 res = ROOT::Fit::FitObject(mg, f1.get(), fitOpts, minOption, drawOpts, drange);
731
732 break;
733 }
735
736 TGraph2D *g2d = dynamic_cast<TGraph2D*>(obj);
737 if (g2d)
738 res = ROOT::Fit::FitObject(g2d, f1.get(), fitOpts, minOption, drawOpts, drange);
739
740 break;
741 }
743 // N/A
744 break;
745 }
746
747 default: {
748 // N/A
749 break;
750 }
751 }
752
753 // After fitting function appears in global list
754 if (f1 && gROOT->GetListOfFunctions()->FindObject(f1.get()))
755 gROOT->GetListOfFunctions()->Remove(f1.get());
756
757 if (m.fSame && f1 && pad) {
758 TF1 *copy = copyTF1(f1.get());
759 copy->SetBit(kCanDelete);
760 copy->Draw("same");
761 }
762
763 if (pad) {
764 pad->Modified();
765 pad->Update();
766 }
767
768 std::string funcname = f1->GetName();
769 if ((funcname.compare(0,4,"prev") == 0) && (funcname.find("-") > 4))
770 funcname.erase(0, funcname.find("-") + 1);
771 funcname = "prev"s + std::to_string(fPrevRes.size() + 1) + "-"s + funcname;
772 f1->SetName(funcname.c_str());
773
774 fPrevRes.emplace_back(m.fSelectedData, f1, res);
775
777
778 SelectFunction("previous::"s + funcname);
779
780 if (save && (gPad != save))
781 gPad = save;
782
783 return true; // provide client with latest changes
784}
785
786////////////////////////////////////////////////////////////////////////////////
787/// Extract color from string
788/// Should be coded as #ff00ff string
789
791{
792 if ((colorid.length() != 7) || (colorid.compare(0,1,"#") != 0)) return 0;
793
794 return TColor::GetColor(colorid.c_str());
795}
796
797////////////////////////////////////////////////////////////////////////////////
798/// Create confidence levels drawing
799/// tab. Then it call Virtual Fitter to perform it.
800
802{
803 if (!result)
804 return nullptr;
805
806 // try to use provided method
807 // auto conf = result->GetConfidenceIntervals();
808 // printf("GET INTERVALS %d\n", (int) conf.size());
809
810 const auto *function = result->FittedFunction();
811 if (!function) {
812 R__LOG_ERROR(FitPanelLog()) << "Fit Function does not exist!";
813 return nullptr;
814 }
815
816 const auto *data = result->FittedBinData();
817 if (!data) {
818 R__LOG_ERROR(FitPanelLog()) << "Unbinned data set cannot draw confidence levels.";
819 return nullptr;
820 }
821
822 std::vector<Double_t> ci(data->Size());
823 result->GetConfidenceIntervals(*data, &ci[0], model().fConfidenceLevel);
824
825 if (model().fDim == 1) {
826 TGraphErrors *g = new TGraphErrors(ci.size());
827 for (unsigned int i = 0; i < ci.size(); ++i) {
828 const Double_t *x = data->Coords(i);
829 const Double_t y = (*function)(x);
830 g->SetPoint(i, *x, y);
831 g->SetPointError(i, 0, ci[i]);
832 }
833 // std::ostringstream os;
834 // os << "Confidence Intervals with " << conflvl << " conf. band.";
835 // g->SetTitle(os.str().c_str());
836 g->SetTitle("Confidence Intervals with");
837
838 auto icol = GetColor(model().fConfidenceColor);
839 g->SetLineColor(icol);
840 g->SetFillColor(icol);
841 g->SetFillStyle(3001);
842 return g;
843 } else if (model().fDim == 2) {
844 TGraph2DErrors *g = new TGraph2DErrors(ci.size());
845 for (unsigned int i = 0; i < ci.size(); ++i) {
846 const Double_t *x = data->Coords(i);
847 const Double_t y = (*function)(x);
848 g->SetPoint(i, x[0], x[1], y);
849 g->SetPointError(i, 0, 0, ci[i]);
850 }
851 // std::ostringstream os;
852 // os << "Confidence Intervals with " << fConfLevel->GetNumber() << " conf. band.";
853 // g->SetTitle(os.str().c_str());
854
855 g->SetTitle("Confidence Intervals with");
856
857 auto icol = GetColor(model().fConfidenceColor);
858 g->SetLineColor(icol);
859 g->SetFillColor(icol);
860 g->SetFillStyle(3001);
861 return g;
862 }
863
864 return nullptr;
865}
866
867////////////////////////////////////////////////////////////////////////////////
868/// Perform drawing using current model settings
869/// Returns true if any action was done
870
872{
873 auto &m = model();
874
875 TObject *obj = GetSelectedObject(m.fSelectedData);
876 if (!obj) return false;
877
878 TObject *drawobj = nullptr;
879 std::string drawopt;
880 bool superimpose = true, objowner = true;
881
882 if (m.fHasAdvanced && (m.fSelectedTab == "Advanced")) {
883
884 TFitResult *res = FindFitResult(m.fSelectedFunc);
885 if (!res) return false;
886
887 if (m.fAdvancedTab == "Contour") {
888
889 superimpose = m.fContourSuperImpose;
890 int par1 = std::stoi(m.fContourPar1Id);
891 int par2 = std::stoi(m.fContourPar2Id);
892
893 TGraph *graph = new TGraph(m.fContourPoints);
894
895 if (!res->Contour(par1, par2, graph, m.fConfidenceLevel)) {
896 delete graph;
897 return false;
898 }
899
900 auto fillcolor = GetColor(m.fContourColor);
901 graph->SetFillColor(fillcolor);
902 graph->GetXaxis()->SetTitle( res->ParName(par1).c_str() );
903 graph->GetYaxis()->SetTitle( res->ParName(par2).c_str() );
904
905 drawobj = graph;
906 drawopt = superimpose ? "LF" : "ALF";
907
908 } else if (m.fAdvancedTab == "Scan") {
909
910 int par = std::stoi(m.fScanId);
911 TGraph *graph = new TGraph( m.fScanPoints);
912 if (!res->Scan( par, graph, m.fScanMin, m.fScanMax)) {
913 delete graph;
914 return false;
915 }
916 auto linecolor = GetColor(m.fScanColor);
917 if (!linecolor) linecolor = kBlue;
918 graph->SetLineColor(linecolor);
919 graph->SetLineWidth(2);
920 graph->GetXaxis()->SetTitle(res->ParName(par).c_str());
921 graph->GetYaxis()->SetTitle("FCN" );
922
923 superimpose = false;
924 drawobj = graph;
925 drawopt = "ALF";
926
927 } else if (m.fAdvancedTab == "Confidence") {
928
929 drawobj = MakeConfidenceLevels(res);
930 drawopt = "C3same";
931
932 } else {
933 return false;
934 }
935 } else {
936
937 // find already existing functions, not try to create something new
938 TF1 *func = FindFunction(m.fSelectedFunc);
939
940 // when "Pars" tab is selected, automatically update function parameters
941 if (func && (m.fSelectedTab.compare("Pars") == 0) && (m.fSelectedFunc == m.fFuncPars.id))
942 m.fFuncPars.SetParameters(func);
943
944 drawobj = func;
945 drawopt = "same";
946 objowner = true;
947 }
948
949 if (!drawobj)
950 return false;
951
952 auto pad = GetDrawPad(obj, true);
953 if (!pad) {
954 if (objowner)
955 delete drawobj;
956 return false;
957 }
958
959 if (!superimpose)
960 pad->Clear();
961
962 if (objowner)
963 drawobj->SetBit(kCanDelete);
964
965 drawobj->Draw(drawopt.c_str());
966
967 pad->Modified();
968 pad->Update();
969
970 return true;
971}
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
short Color_t
Definition RtypesCore.h:92
@ kBlue
Definition Rtypes.h:66
#define gDirectory
Definition TDirectory.h:385
XFontStruct * id
Definition TGX11.cxx:109
char name[80]
Definition TGX11.cxx:110
float xmin
float ymin
float xmax
float ymax
@ kCanDelete
Definition TObject.h:369
#define gROOT
Definition TROOT.h:404
char * Form(const char *fmt,...)
#define gPad
void Show(const std::string &where="")
show FitPanel in specified place
bool DoFit()
Perform fitting using current model settings Returns true if any action was done.
void AssignHistogram(TH1 *hist)
Assign histogram to use with fit panel - without ownership.
std::unique_ptr< TF1 > GetFitFunction(const std::string &funcid)
Creates new instance to make fitting.
void SelectFunction(const std::string &funcid)
Select fit function.
RFitPanelModel::EFitObjectType GetFitObjectType(TObject *obj)
Returns kind of object.
std::shared_ptr< RCanvas > fCanvas
! v7 canvas used to display results
Definition RFitPanel.hxx:45
void SendModel()
Send model object to the client.
std::shared_ptr< RWebWindow > fWindow
! configured display
Definition RFitPanel.hxx:48
std::string fCanvName
! v6 canvas name used to display fit, will be created if not exists
Definition RFitPanel.hxx:42
void GetFunctionsFromSystem()
Looks for all the functions registered in the current ROOT session.
std::unique_ptr< RFitPanelModel > fModel
Definition RFitPanel.hxx:39
void Hide()
hide FitPanel
unsigned fConnId
! client connection id
Definition RFitPanel.hxx:49
int UpdateModel(const std::string &json)
Update fit model returns -1 if JSON fails return 0 if nothing large changed return 1 if important sel...
TF1 * copyTF1(TF1 *f)
Copies f into a new TF1 to be stored in the fitpanel with it's own ownership.
TPad * GetDrawPad(TObject *obj, bool force=false)
Returns pad where histogram is drawn If canvas not exists, create new one.
std::shared_ptr< RWebWindow > GetWindow()
Returns RWebWindow instance, used to display FitPanel.
Definition RFitPanel.cxx:94
void SelectObject(const std::string &objid)
Select object for fitting.
std::string fPadName
! v6 pad name in the canvas, where object is (was) drawn
Definition RFitPanel.hxx:43
TObject * GetSelectedObject(const std::string &objid)
Returns object based on it string id Searches either in gDirectory or in internal panel list.
std::vector< TObject * > fObjects
! objects provided directly to panel for fitting
Definition RFitPanel.hxx:41
bool DoDraw()
Perform drawing using current model settings Returns true if any action was done.
Color_t GetColor(const std::string &colorid)
Extract color from string Should be coded as #ff00ff string.
void UpdateFunctionsList()
Update list of available functions.
RFitPanelModel & model()
Return reference on model object Model created if was not exists before.
std::shared_ptr< RH1D > fFitHist
! v7 histogram for fitting
Definition RFitPanel.hxx:46
TObject * MakeConfidenceLevels(TFitResult *res)
Create confidence levels drawing tab.
TF1 * FindFunction(const std::string &funcid)
Search for existing functions, ownership still belongs to FitPanel or global lists.
void ProcessData(unsigned connid, const std::string &arg)
Process data from FitPanel OpenUI5-based FitPanel sends commands or status changes.
TFitResult * FindFitResult(const std::string &funcid)
Creates new instance to make fitting.
void UpdateDataSet()
Update list of available data.
std::vector< std::unique_ptr< TF1 > > fSystemFuncs
! local copy of all internal system funcs
Definition RFitPanel.hxx:51
RFitPanel(const std::string &title="Fit panel")
Constructor.
Definition RFitPanel.cxx:76
std::list< FitRes > fPrevRes
! all previous functions used for fitting
Definition RFitPanel.hxx:62
void AssignCanvas(const std::string &cname)
static std::shared_ptr< RWebWindow > Create()
Create new RWebWindow Using default RWebWindowsManager.
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition DataRange.h:35
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
const BinData * FittedBinData() const
return BinData used in the fit (return a nullptr in case a different fit is done or the data are not ...
void GetConfidenceIntervals(unsigned int n, unsigned int stride1, unsigned int stride2, const double *x, double *ci, double cl=0.95, bool norm=false) const
get confidence intervals for an array of n points x.
std::string ParName(unsigned int i) const
name of the parameter
const IModelFunction * FittedFunction() const
fitting quantities
Definition FitResult.h:148
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
Definition TBufferJSON.h:75
The Canvas class.
Definition TCanvas.h:23
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1822
1-Dim function class
Definition TF1.h:213
virtual void Copy(TObject &f1) const
Copy this F1 to a new F1.
Definition TF1.cxx:1000
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition TF1.cxx:3539
virtual void SetParent(TObject *p=0)
Definition TF1.h:665
virtual TString GetExpFormula(Option_t *option="") const
Definition TF1.h:461
virtual void Draw(Option_t *option="")
Draw this function with its current attributes.
Definition TF1.cxx:1328
virtual void Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
Save values of function in array fSave.
Definition TF1.cxx:3154
virtual Bool_t AddToGlobalList(Bool_t on=kTRUE)
Add to global list of functions (gROOT->GetListOfFunctions() ) return previous status (true if the fu...
Definition TF1.cxx:841
A 2-Dim function with parameters.
Definition TF2.h:29
virtual void Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
Save values of function in array fSave.
Definition TF2.cxx:799
virtual void Copy(TObject &f2) const
Copy this F2 to a new F2.
Definition TF2.cxx:211
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:148
A 3-Dim function with parameters.
Definition TF3.h:28
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition TF3.h:145
virtual void Copy(TObject &f3) const
Copy this F3 to a new F3.
Definition TF3.cxx:153
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
Extends the ROOT::Fit::Result class with a TNamed inheritance providing easy possibility for I/O.
Definition TFitResult.h:34
bool Contour(unsigned int ipar, unsigned int jpar, TGraph *gr, double confLevel=0.683)
Create a 2D contour around the minimum for the parameter ipar and jpar if a minimum does not exist or...
bool Scan(unsigned int ipar, TGraph *gr, double xmin=0, double xmax=0)
Scan parameter ipar between value of xmin and xmax A graph must be given which will be on return fill...
Graph 2D class with errors.
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
A TGraphErrors is a TGraph with error bars.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
The Histogram stack class.
Definition THStack.h:38
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:36
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Clear(Option_t *="")
Definition TObject.h:119
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:429
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:200
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:393
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:766
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:515
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:267
The most important graphics class in the ROOT system.
Definition TPad.h:26
TList * GetListOfPrimitives() const override
Definition TPad.h:239
const char * GetName() const override
Returns name of object.
Definition TPad.h:254
Basic string class.
Definition TString.h:136
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
TGraphErrors * gr
Definition legend1.C:25
TF1 * f1
Definition legend1.C:11
RLogChannel & FitPanelLog()
Log channel for FitPanel diagnostics.
TFitResultPtr FitObject(TH1 *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
fitting function for a TH1 (called from TH1::Fit)
Definition HFitImpl.cxx:965
Definition graph.py:1
Data structure for the fit panel.
std::string fSelectedData
selected data
std::string fSelectedFunc
id of selected fit function like dflt::gaus
void UpdateAdvanced(TFitResult *res)
Update advanced parameters associated with fit function.
void SelectedFunc(const std::string &name, TF1 *func)
Select function.
std::string fTitle
title of the fit panel
auto * m
Definition textangle.C:8