Replace Minuit2 in PluginManager

Dear experts,

I want to use a slightly modified Minuit2Minimizer class for my analysis. Since I’m using the conda version of ROOT v6.24, I cannot recompile the source code. I wrote some c++ code (attached) and compiled it into a shared library. Then I added the new class to PluginManager and to force Factory.cxx to instantiate my implementation but it clearly did not worked, since the dynamic cast failed.

The question is: how can I properly add my modified Minuit2Minimizer to PluginManager so that RooFit uses it instead of the default Minuit2Minimizer?

To run the test scripts:

g++ -O3 -Wall -fPIC -W -I. $( root-config --cflags ) $( root-config --libs ) -lRooFitCore -lRooFit -lMinuit2 Minuit3Minimizer.cxx -shared -o libMinuit3Minimizer.so
g++ -O3 -Wall -fPIC -W -I. $( root-config --cflags ) $( root-config --libs ) -lRooFitCore -lRooFit -lMinuit2 -Wl,-rpath=. -L. -lMinuit3Minimizer test_Minuit3.C -o test_Minuit3
./test_Minuit3

A feature request: Can Minuit2Minimizer expose the fMinimum private member variable via a public function? Being able to get the first derivatives is very useful to debug problematic and complex fits. I know Minuit2 can print first derivatives with printLevel set to DEBUG, but the log files are excessively large and I need to parse the strings into floats.

Thank you for looking at my post!

Minuit3Minimizer.cxx (43.3 KB)
Minuit3Minimizer.h (12.6 KB)
test_Minuit3.C (2.7 KB)

Hi @Da_Yu_Tou ,

Thank you for posting your question on the forum! You are very close to a working example, just a couple of small details left in your test_Minuit3.C script:

  1. Other than loading the shared library, you should also declare the header with the class definition for things to be properly setup, just add a call to

    gInterpreter->Declare("#include \"Minuit3Minimizer.h\"");
    

    Before calling gSystem->Load().

  2. The call to the plugin manager needs to be slightly modified, from your initial example:

    TPluginManager *pm = gROOT->GetPluginManager();
    pm->AddHandler(
        "ROOT::Math::Minimizer",
        "Minuit2",
        "ROOT::Minuit2::Minuit3Minimizer",
        "Minuit2",
        "Minuit3Minimizer(const char *)");
    

    to (you can directly use the gPluginMgr object)

    gPluginMgr->AddHandler(
    "ROOT::Math::Minimizer",
    "MyMinimizerName", // needs to match the call to minimizer.setMinimizerType
    "ROOT::Minuit2::Minuit3Minimizer",
    "Minuit3Minimizer",
    "Minuit3Minimizer(const char *)");
    

    Note especially that the secret sauce is the second argument to this function. Here I used the randomly chosen name MyMinimizerName, this name needs to match what you are calling later on in the line minimizer.setMinimizerType("MyMinimizerName") (it can actually be also a matching regex, but for simplicity and sanity it’s easier if it just matches 1:1).

Let me know if this helps.

Cheers,
Vincenzo

Hi Vincenzo,

Thanks for the solution! It works perfectly.

Cheers,
Da Yu

Dear Vincenzo,

One more question about implementing this in an analysis. It seems I have to add the include path and library path to gInterpreter during runtime.

    gInterpreter->AddIncludePath(HEADER_DIR);
    gInterpreter->Declare("#include \"Minuit3Minimizer.h\"");
    gSystem->AddDynamicPath(MYLIB_DIR);
    gSystem->Load("libMinuit3Minimizer");

This is despite me baking the library path into my executable (note rpath)

g++ -O3 -Wall -fPIC -W -I. $( root-config --cflags ) $( root-config --libs ) -lRooFitCore -lRooFit -lMinuit2 -Wl,-rpath=<dir/to/libMinuit3Minimizer> -L<dir/to/libMinuit3Minimizer> -lMinuit3Minimizer test_Minuit3.C -o test_Minuit3

Is this unavoidable for the shared lib directory? I guess the another method is to set environment variables PATH (for header) and LD_LIBRARY_PATH (for shared library).

Cheers,
Da Yu

Hi,

That is indeed a good question. I guess here the problem is more letting the ROOT interpreter know where it can find headers/shared libraries (i.e. include path and dynamic path) rather than embedding that information in the library itself with the rpath. So I would say that indeed you need to extend those variables somehow (either of the two approaches that you describe should work).

I will invite @pcanal or @vvassilev to comment further if I’m missing anything here.

Cheers,
Vincenzo