Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8164747
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T19:23:05+00:00 2026-06-06T19:23:05+00:00

I am writing an automated curve fitting routine for 2D data based on scipy’s

  • 0

I am writing an automated curve fitting routine for 2D data based on scipy’s optimize.leastsq, and it works. However when adding many curves with starting values slighly off I get non-physical results (negative amplitude, for example).

I found this post Scipy: bounds for fitting parameter(s) when using optimize.leastsq and was trying to use the parameter transformation according to Minuit from Cern. In the above mentioned question somebody provided a link to some python code.

code.google.com/p/nmrglue/source/browse/trunk/nmrglue/analysis/leastsqbound.py

I wrote this minimal working example (extending the code)

"""
http://code.google.com/p/nmrglue/source/browse/trunk/nmrglue/analysis/leastsqbound.py
Constrained multivariate Levenberg-Marquardt optimization
"""

from scipy.optimize import leastsq
import numpy as np
import matplotlib.pyplot as plt #new

def internal2external_grad(xi, bounds):
    """ 
    Calculate the internal to external gradiant

    Calculates the partial of external over internal

    """

    ge = np.empty_like(xi)

    for i, (v, bound) in enumerate(zip(xi, bounds)):

        a = bound[0]    # minimum
        b = bound[1]    # maximum

        if a == None and b == None:    # No constraints
            ge[i] = 1.0

        elif b == None:      # only min
            ge[i] = v / np.sqrt(v ** 2 + 1)

        elif a == None:      # only max
            ge[i] = -v / np.sqrt(v ** 2 + 1)

        else:       # both min and max
            ge[i] = (b - a) * np.cos(v) / 2.

    return ge

def i2e_cov_x(xi, bounds, cov_x):

    grad = internal2external_grad(xi, bounds)
    grad = grad = np.atleast_2d(grad)
    return np.dot(grad.T, grad) * cov_x


def internal2external(xi, bounds):
    """ Convert a series of internal variables to external variables"""

    xe = np.empty_like(xi)

    for i, (v, bound) in enumerate(zip(xi, bounds)):

        a = bound[0]    # minimum
        b = bound[1]    # maximum

        if a == None and b == None:    # No constraints
            xe[i] = v

        elif b == None:      # only min
            xe[i] = a - 1. + np.sqrt(v ** 2. + 1.)

        elif a == None:      # only max
            xe[i] = b + 1. - np.sqrt(v ** 2. + 1.)

        else:       # both min and max
            xe[i] = a + ((b - a) / 2.) * (np.sin(v) + 1.)

    return xe

def external2internal(xe, bounds):
    """ Convert a series of external variables to internal variables"""

    xi = np.empty_like(xe)

    for i, (v, bound) in enumerate(zip(xe, bounds)):

        a = bound[0]    # minimum
        b = bound[1]    # maximum

        if a == None and b == None: # No constraints
            xi[i] = v

        elif b == None:     # only min
            xi[i] = np.sqrt((v - a + 1.) ** 2. - 1)

        elif a == None:     # only max
            xi[i] = np.sqrt((b - v + 1.) ** 2. - 1)

        else:   # both min and max
            xi[i] = np.arcsin((2.*(v - a) / (b - a)) - 1.)

    return xi

def err(p, bounds, efunc, args):

    pe = internal2external(p, bounds)    # convert to external variables
    return efunc(pe, *args)

def calc_cov_x(infodic, p):
    """
    Calculate cov_x from fjac, ipvt and p as is done in leastsq
    """

    fjac = infodic['fjac']
    ipvt = infodic['ipvt']
    n = len(p)

    # adapted from leastsq function in scipy/optimize/minpack.py
    perm = np.take(np.eye(n), ipvt - 1, 0)
    r = np.triu(np.transpose(fjac)[:n, :])
    R = np.dot(r, perm)
    try:
        cov_x = np.linalg.inv(np.dot(np.transpose(R), R))
    except LinAlgError:
        cov_x = None
    return cov_x


def leastsqbound(func, x0, bounds, args = (), **kw):
    """
    Constrained multivariant Levenberg-Marquard optimization

    Minimize the sum of squares of a given function using the 
    Levenberg-Marquard algorithm. Contraints on parameters are inforced using 
    variable transformations as described in the MINUIT User's Guide by
    Fred James and Matthias Winkler.

    Parameters:

    * func      functions to call for optimization.
    * x0        Starting estimate for the minimization.
    * bounds    (min,max) pair for each element of x, defining the bounds on
                that parameter.  Use None for one of min or max when there is
                no bound in that direction.
    * args      Any extra arguments to func are places in this tuple.

    Returns: (x,{cov_x,infodict,mesg},ier)

    Return is described in the scipy.optimize.leastsq function.  x and con_v  
    are corrected to take into account the parameter transformation, infodic 
    is not corrected.

    Additional keyword arguments are passed directly to the 
    scipy.optimize.leastsq algorithm. 

    """
    # check for full output
    if "full_output" in kw and kw["full_output"]:
        full = True
    else:
        full = False

    # convert x0 to internal variables
    i0 = external2internal(x0, bounds)

    # perfrom unconstrained optimization using internal variables
    r = leastsq(err, i0, args = (bounds, func, args), **kw)

    # unpack return convert to external variables and return
    if full:
        xi, cov_xi, infodic, mesg, ier = r
        xe = internal2external(xi, bounds)
        cov_xe = i2e_cov_x(xi, bounds, cov_xi)
        # XXX correct infodic 'fjac','ipvt', and 'qtf' 
        return xe, cov_xe, infodic, mesg, ier

    else:
        xi, ier = r
        xe = internal2external(xi, bounds)
        return xe, ier


# new below

def _evaluate(x, p):
    '''
    Linear plus Lorentzian curve
    p = list with three parameters ([a, b, I, Pos, FWHM])
    '''
    return p[0] + p[1] * x + p[2] / (1 + np.power((x - p[3]) / (p[4] / 2), 2))


def residuals(p, y, x):

    err = _evaluate(x, p) - y
    return err


if __name__ == '__main__':
    data = np.loadtxt('constraint.dat') # read data

    p0 = [5000., 0., 500., 2450., 3] #Start values for a, b, I, Pos, FWHM
    constraints = [(4000., None), (-50., 20.), (0., 2000.), (2400., 2451.), (None, None)]

    p, res = leastsqbound(residuals, p0, constraints, args = (data[:, 1], data[:, 0]), maxfev = 20000)
    print p, res

    plt.plot(data[:, 0], data[:, 1]) # plot data
    plt.plot(data[:, 0], _evaluate(data[:, 0], p0)) # plot start values
    plt.plot(data[:, 0], _evaluate(data[:, 0], p)) # plot fit values
    plt.show()

Thats the plot output, where green is the starting conditions and red the fit result:
plot results

Is this the correct usage? External2internal conversion just throws a nan if outside the bounds. leastsq seems to be able to handle this?

I uploaded the fitting data here. Just paste into a text file named constraint.dat.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T19:23:07+00:00Added an answer on June 6, 2026 at 7:23 pm

    There is already an existing popular constrained Lev-Mar code

    http://adsabs.harvard.edu/abs/2009ASPC..411..251M

    with the implementation in python

    http://code.google.com/p/astrolibpy/source/browse/mpfit/mpfit.py

    I would suggest not to reinvent the wheel.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm writing automated UI tests in C# using Selenium 2 Web Driver for web
I have been using Selenium Library with Robot Framework for writing automated tests for
I'm writing some automated acceptance tests for a flash movie (driving the movie using
I am writing an automated test script in python and I need to integrate
I'm writing some automated tests using Capybara/RSpec, I choose/configure the driver by using this
Here's the situation. I'm writing an automated test that walks the list of dependencies
I'm writing an aggregation application which scrapes data from a couple of web sources
I'm writing an automated test to determine whether or not rtf files are successfully
I'm writing a VMWare ESX automated build script and I'm falling at the last
I'm currently writing a HMI for an automated machine in VB.Net 2010. I have

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.