From fcd19beb42be67cb160d90f66bd214698f7a0fc2 Mon Sep 17 00:00:00 2001 From: Sergey Linev <S.Linev@gsi.de> Date: Wed, 15 May 2019 16:28:54 +0200 Subject: [PATCH] web fitpanel: improve TCanvas management Search for object in sub-sub pads before creating new TCanvas. Drawing copy of function - do not keep stale pointer as was done by previous panel --- gui/fitpanelv7/inc/ROOT/RFitPanel.hxx | 2 +- gui/fitpanelv7/inc/ROOT/RFitPanelModel.hxx | 11 ++- gui/fitpanelv7/src/RFitPanel.cxx | 96 +++++++++++++--------- gui/fitpanelv7/src/RFitPanelModel.cxx | 49 ++++------- 4 files changed, 82 insertions(+), 76 deletions(-) diff --git a/gui/fitpanelv7/inc/ROOT/RFitPanel.hxx b/gui/fitpanelv7/inc/ROOT/RFitPanel.hxx index 41f2f2b0ba2..7cef67e268c 100644 --- a/gui/fitpanelv7/inc/ROOT/RFitPanel.hxx +++ b/gui/fitpanelv7/inc/ROOT/RFitPanel.hxx @@ -43,7 +43,7 @@ class RFitPanel { std::unique_ptr<RFitPanelModel> fModel; std::vector<TObject*> fObjects; ///<! objects provided directly to panel for fitting - std::string fCanvName{"c1"}; ///<! v6 canvas name used to display fit, will be created if not exists + std::string fCanvName; ///<! v6 canvas name used to display fit, will be created if not exists std::shared_ptr<RCanvas> fCanvas; ///!< v7 canvas used to display results std::shared_ptr<RH1D> fFitHist; ///!< v7 histogram for fitting diff --git a/gui/fitpanelv7/inc/ROOT/RFitPanelModel.hxx b/gui/fitpanelv7/inc/ROOT/RFitPanelModel.hxx index 3e93ad6a2f1..3450d0434ee 100644 --- a/gui/fitpanelv7/inc/ROOT/RFitPanelModel.hxx +++ b/gui/fitpanelv7/inc/ROOT/RFitPanelModel.hxx @@ -20,6 +20,7 @@ #include "Foption.h" #include "Fit/DataRange.h" #include "Math/MinimizerOptions.h" +#include "TString.h" #include <vector> #include <string> @@ -196,13 +197,11 @@ struct RFitPanelModel { bool IsDataSelected() const { return !fSelectedData.empty(); } - void GetRanges(ROOT::Fit::DataRange &drange); - void GetFitOptions(Foption_t &fitOpts); - void GetMinimizerOptions(ROOT::Math::MinimizerOptions &minOpts); + ROOT::Fit::DataRange GetRanges(); + Foption_t GetFitOptions(); + ROOT::Math::MinimizerOptions GetMinimizerOptions(); - std::string GetDrawOption(); - - std::string GetFitOption(); + TString GetDrawOption(); }; } // namespace Experimental diff --git a/gui/fitpanelv7/src/RFitPanel.cxx b/gui/fitpanelv7/src/RFitPanel.cxx index df5514ea1cb..09126312d32 100644 --- a/gui/fitpanelv7/src/RFitPanel.cxx +++ b/gui/fitpanelv7/src/RFitPanel.cxx @@ -451,8 +451,7 @@ std::unique_ptr<TF1> ROOT::Experimental::RFitPanel::GetFitFunction(const std::st std::string formula = funcname.substr(6); - ROOT::Fit::DataRange drange; - model().GetRanges(drange); + ROOT::Fit::DataRange drange = model().GetRanges(); double xmin, xmax, ymin, ymax, zmin, zmax; drange.GetRange(xmin, xmax, ymin, ymax, zmin, zmax); @@ -537,35 +536,62 @@ void ROOT::Experimental::RFitPanel::DrawScan(const std::string &model) // printf("SCAN Points %d, Par %d, Min %d, Max %d\n", obj->fScanPoints, obj->fScanPar, obj->fScanMin, obj->fScanMax); } -/// Returns pad where histogram should be drawn -/// Ensure that histogram is on the first place +/////////////////////////////////////////////////////////////////// +/// Returns pad where histogram is drawn +/// If canvas not exists, create new one TPad *ROOT::Experimental::RFitPanel::GetDrawPad(TObject *obj) { - if (model().fNoDrawing || model().fNoStoreDraw) + if (!obj || model().fNoDrawing || model().fNoStoreDraw) return nullptr; + std::function<TPad*(TPad*)> check = [&](TPad *pad) { + TPad *res = nullptr; + if (pad) { + TIter next(pad->GetListOfPrimitives()); + TObject *prim = nullptr; + while (!res && (prim = next())) { + res = (prim == obj) ? pad : check(dynamic_cast<TPad *>(prim)); + } + } - if (fCanvName.empty()) { - gPad = nullptr; - return nullptr; - } + return res; + }; - TCanvas *canv = (TCanvas *) gROOT->GetListOfCanvases()->FindObject(fCanvName.c_str()); + if (!fCanvName.empty()) { + auto drawcanv = dynamic_cast<TCanvas *> (gROOT->GetListOfCanvases()->FindObject(fCanvName.c_str())); + auto drawpad = check(drawcanv); + if (drawpad) { + drawpad->cd(); + return drawpad; + } + if (drawcanv) { + drawcanv->Clear(); + drawcanv->cd(); + obj->Draw(); + return drawcanv; + } + fCanvName.clear(); + } - if (!canv) { - canv = gROOT->MakeDefCanvas(); - canv->SetName(fCanvName.c_str()); - canv->SetTitle("Fit panel drawings"); + TObject *c = nullptr; + TIter nextc(gROOT->GetListOfCanvases()); + while ((c = nextc())) { + auto drawpad = check(dynamic_cast<TCanvas* >(c)); + if (drawpad) { + drawpad->cd(); + fCanvName = c->GetName(); + return drawpad; + } } - canv->cd(); + auto canv = gROOT->MakeDefCanvas(); + canv->SetName("fpc"); + canv->SetTitle("Fit panel drawings"); + fCanvName = canv->GetName(); - // TODO: provide proper draw options - if (obj && !canv->FindObject(obj)) { - canv->Clear(); - obj->Draw(); - } + canv->cd(); + obj->Draw(); return canv; } @@ -705,17 +731,10 @@ bool ROOT::Experimental::RFitPanel::DoFit() auto f1 = GetFitFunction(m.fSelectedFunc); if (!f1) return false; - ROOT::Fit::DataRange drange; - ROOT::Math::MinimizerOptions minOption; - Foption_t fitOpts; - - m.GetRanges(drange); - m.GetFitOptions(fitOpts); - m.GetMinimizerOptions(minOption); - - // std::string drawOpts = m.GetDrawOption(); - - TString strDrawOpts; + auto drange = m.GetRanges(); + auto minOption = m.GetMinimizerOptions(); + auto fitOpts = m.GetFitOptions(); + auto drawOpts = m.GetDrawOption(); TVirtualPad *save = gPad; @@ -726,7 +745,7 @@ bool ROOT::Experimental::RFitPanel::DoFit() TH1 *hist = dynamic_cast<TH1*>(obj); if (hist) - ROOT::Fit::FitObject(hist, f1.get(), fitOpts, minOption, strDrawOpts, drange); + ROOT::Fit::FitObject(hist, f1.get(), fitOpts, minOption, drawOpts, drange); break; } @@ -734,14 +753,14 @@ bool ROOT::Experimental::RFitPanel::DoFit() TGraph *gr = dynamic_cast<TGraph*>(obj); if (gr) - ROOT::Fit::FitObject(gr, f1.get(), fitOpts, minOption, strDrawOpts, drange); + ROOT::Fit::FitObject(gr, f1.get(), fitOpts, minOption, drawOpts, drange); break; } case kObjectMultiGraph: { TMultiGraph *mg = dynamic_cast<TMultiGraph*>(obj); if (mg) - ROOT::Fit::FitObject(mg, f1.get(), fitOpts, minOption, strDrawOpts, drange); + ROOT::Fit::FitObject(mg, f1.get(), fitOpts, minOption, drawOpts, drange); break; } @@ -749,7 +768,7 @@ bool ROOT::Experimental::RFitPanel::DoFit() TGraph2D *g2d = dynamic_cast<TGraph2D*>(obj); if (g2d) - ROOT::Fit::FitObject(g2d, f1.get(), fitOpts, minOption, strDrawOpts, drange); + ROOT::Fit::FitObject(g2d, f1.get(), fitOpts, minOption, drawOpts, drange); break; } @@ -764,8 +783,11 @@ bool ROOT::Experimental::RFitPanel::DoFit() } } - if (m.fSame && f1) - f1->Draw("same"); + if (m.fSame && f1) { + TF1 *copy = copyTF1(f1.get()); + copy->SetBit(kCanDelete); + copy->Draw("same"); + } if (pad) { pad->Modified(); diff --git a/gui/fitpanelv7/src/RFitPanelModel.cxx b/gui/fitpanelv7/src/RFitPanelModel.cxx index b13ea858a7b..acff1be268a 100644 --- a/gui/fitpanelv7/src/RFitPanelModel.cxx +++ b/gui/fitpanelv7/src/RFitPanelModel.cxx @@ -238,44 +238,22 @@ void ROOT::Experimental::RFitPanelModel::UpdateAdvanced(TF1 *func) } -std::string ROOT::Experimental::RFitPanelModel::GetFitOption() +ROOT::Fit::DataRange ROOT::Experimental::RFitPanelModel::GetRanges() { - std::string opt = fFitMethod; + ROOT::Fit::DataRange drange; - if (fIntegral) opt.append("I"); - if (fUseRange) opt.append("R"); - if (fBestErrors) opt.append("E"); - if (fImproveFitResults) opt.append("M"); - if (fAddToList) opt.append("+"); - if (fUseGradient) opt.append("G"); - - if (fEmptyBins1) - opt.append("WW"); - else if (fAllWeights1) - opt.append("W"); - - if (fNoStoreDraw) - opt.append("N"); - else if (fNoDrawing) - opt.append("O"); - - return opt; -} - -void ROOT::Experimental::RFitPanelModel::GetRanges(ROOT::Fit::DataRange &drange) -{ - if (fDim > 0) { + if (fDim > 0) drange.AddRange(0, fRangeX[0], fRangeX[1]); - } - if ( fDim > 1 ) { + if ( fDim > 1 ) drange.AddRange(1, fRangeY[0], fRangeY[1]); - } + return drange; } -void ROOT::Experimental::RFitPanelModel::GetFitOptions(Foption_t &fitOpts) +Foption_t ROOT::Experimental::RFitPanelModel::GetFitOptions() { + Foption_t fitOpts; fitOpts.Range = fUseRange; fitOpts.Integral = fIntegral; fitOpts.More = fImproveFitResults; @@ -312,10 +290,14 @@ void ROOT::Experimental::RFitPanelModel::GetFitOptions(Foption_t &fitOpts) fitOpts.Robust = 1; fitOpts.hRobust = fRobustLevel; } + + return fitOpts; } -void ROOT::Experimental::RFitPanelModel::GetMinimizerOptions(ROOT::Math::MinimizerOptions &minOpts) +ROOT::Math::MinimizerOptions ROOT::Experimental::RFitPanelModel::GetMinimizerOptions() { + ROOT::Math::MinimizerOptions minOpts; + if (fLibrary == 0) minOpts.SetMinimizerType ( "Minuit"); else if (fLibrary == 1) @@ -363,11 +345,14 @@ void ROOT::Experimental::RFitPanelModel::GetMinimizerOptions(ROOT::Math::Minimiz minOpts.SetTolerance(fMaxTolerance); minOpts.SetMaxIterations(fMaxIterations); minOpts.SetMaxFunctionCalls(fMaxIterations); + + return minOpts; } -std::string ROOT::Experimental::RFitPanelModel::GetDrawOption() +TString ROOT::Experimental::RFitPanelModel::GetDrawOption() { - return ""; + TString res; + return res; } -- GitLab