New to ROOT, hoping it has a solution to my problem. Tried to fit a curve using GSL

Hi,
I keep getting an error and the only relevant hit I got using google was on this forum (for some reason I’m not allowed to link the post)

I’m trying to fit a non-linear curve using GSL (we have 1.15 here) I can’t compute the partial derivative of this curve with respect to it’s input parameters, or at least I don’t know how to. The curve represents the envelope of a frequency that’s send to a magnet in the LHC.

I used scipy.curve_fit in python and it worked like magic, but now I need to translate it in C++. I tried calculating the Jacobian matrix, but I think I did that wrong. I tried looking into the scipy.curve_fit implementation, but when I went down that rabbit hole I found myself looking at a Fortran implementation of GSL and now I’m even more lost.

I’m hoping to find a solution to fit a function here. does anyone have any experience in this?

This is the function I’m trying to fit, it basically looks like a trapezoid. it’s 0 before start, has a linear rising edge up until the flat top, is “almost” flat at the flat top and then a linear falling edge until its 0 again.

std::vector<double> envelope(std::vector<double> timestamps, double start, double startFlt, double endFlt, double end, double startAmpl, double endAmpl) {
    std::vector<double> result(timestamps.size(), 0);
    double startSlope = startAmpl/(startFlt-start);
    double fltSlope = (endAmpl - startAmpl) / (endFlt - startFlt);
    double endSlope = (-endAmpl/(end-endFlt));
    for (size_t i=0; i<result.size(); i++) {
        double timestamp = timestamps[i];
        if (timestamp < start) {
            // do nothing, is already initialized to zero
        } else if (timestamp < startFlt) {
            result[i] = (startSlope * (timestamp - start));
        } else if (timestamp < endFlt) {
            result[i] = (fltSlope * (timestamp - startFlt) + startAmpl);
        } else if (timestamp < end) {
            result[i] = (endSlope * (timestamp - endFlt) + endAmpl);
        } else {
            // do nothing, is already initialized to zero
        }
    }
    return result;
}

Oh and by the way. The tutorial of installing ROOT mentions cmake, is there a way by using makefile?

Hi @Koen_van_Wel,

Don’t know whether it can help, but I’m inviting @jonas and @moneta -our RooFit experts- to this topic. Maybe the can suggest you something useful.

No, ROOT build system is based on CMake. However, if you want to install ROOT, we encourage you to install it via a pre-compiled binary package or through Conda. See Installing ROOT - ROOT for detailed instructions.

Cheers,
J.

Hi @jalopezg

Thank you for your reply. I’ll await the other suggestions.

No, ROOT build system is based on CMake. However, if you want to install ROOT

I think I misspoke. I meant, can I include root in my c++ project that uses makefile? I couldn’t find documentation on that. I 'm working through --root url–/install/build_from_source/

In an effort to supply more information:

I’m currently working with c++03 and gsl v1.15 is installed on the FEC. I can use c++11 while building ROOT from source, although I am stuck with gcc v4.8.5 (which has c++11 as an experimental feature) and cmake v2.8.12.2.

I found this forum because the error I was getting is spoken about here: --forum url–/t/gsl-cannot-reach-the-specified-tolerance/12172

I was using gsl_multifit_fdfsolver, because there is no implementation of gsl_multifit_fsolver_type in GSL v1.15 yet. I suspect I need to use ROOT::Math::GSLMultiFit in a way, but I’m not if it is the right solution.

Cheers,
Koen

PS. Why cant I link to other urls?

Try: grep -r gsl_multifit_fsolver_type /usr/include/gsl

With GCC 4.8.5, you can use the ROOT 6.24 patches branch or some older version.

I guess you should be able to “upgrade” your CMake (e.g., you could take the “cmake.org” binaries or the “cmake3” package from the “EPEL” repository).

You can use ordinary makefiles for your own projects. There exist plenty of examples, e.g., grab the ROOT source code, cd root_source_dir, and then: find t[eu]* -name "*akefile*"

Thanks, I’ll look into it! Do you know what I need from ROOT to do a fit like this?

Try: grep -r gsl_multifit_fsolver_type /usr/include/gsl

Yes the type exists, but there’s no implementation. Here’s the doc on gsl v1.15

38.7 Minimization Algorithms without Derivatives
There are no algorithms implemented in this section at the moment.

I don’t really understand what you expect / miss.

I tried “GSL 2.7.1” and “GSL 1.15” and for both of them, I got almost the same output when I tried:
grep -r gsl_multifit_fsolver /usr/include/gsl

The “GSL 2.7.1” has one more function named “gsl_multifit_fsolver_driver”.

For what is available in ROOT, see, e.g.:

You can try the “GSLMultiFit” with the combinedFit2.C macro and/or the ${ROOTSYS}/tutorials/fit/NumericalMinimization.C macro.

UPDATE: @moneta Out of these two “tutorials” mentioned above, the combinedFit2.C macro breaks with ROOT 6.28 (it’s fine with older releases) and the ${ROOTSYS}/tutorials/fit/NumericalMinimization.C macro dies with any version (when the “GSLMultiFit” is tried).

Hi,

The GSLMultiFit method works only for least-square and likelihood fits. It requires that the function you minimise is a derived class of ROOT::Math::BasicFitMethodFunction.
For this is expected that the NumericalMinimization.C tutorial does not work in this case, since it applies to minimise a generic function.

Lorenzo

@moneta Well, the ${ROOTSYS}/tutorials/fit/NumericalMinimization.C macro explicitly lists available choices for “minimizes” and “specific algorithms” (so maybe one should “clean” this list there).

Thank you @Wile_E_Coyote for reporting this, I will update that list in the tutorial documentation.

Here it is also the updated macro combinedFit2.C working with the 6.28 releases (and older versions)

Lorenzo

combinedFit2.C (6.0 KB)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.