0

I am currently trying several methods to fit and afterwards transform some data using a 2nd degree polynomial function. I have been using the following code to that end:

import matplotlib.pyplot as plt
import numpy
from scipy.optimize import curve_fit

def fitFunc(self, x,a,b,c):
    return a*x**2 + b*x + c

def calcQuadratic(self,data):
    """ This function fits the specified function in 'fitFunc'
    to the data, using the curve_fit package from scipy.optimize.

    INPUT: A list of (m/z,int) tuples
    OUTPUT: The parameters for the fitted function
    """
    expected = []
    observed = []
    for i in data:
        expected.append(i[0])
        observed.append(i[1])
    z = curve_fit(self.fitFunc, observed, expected)
    #############
    # Plot Code #
    #############
    newX = numpy.linspace(0,400,2500)
    yNew = self.fitFunc(newX,*z[0])
    fig =  plt.figure()
    ax = fig.add_subplot(111)
    plt.scatter(expected,observed,label='raw')
    plt.plot(newX,yNew,label='obs-exp')
    plt.legend()
    plt.show()
    ###############
    # end of plot #
    ###############
    return z[0]

Subsequently I transform the data by doing basically:

   new = []
   for i in data:
      new.append((fitFunc(i[0],*z[0]),i[1]))

Problem

The above transformation can result in my Y-intercept having a positive X-value. The result of that is that after the transformation, I have data that is now found at the same value (see the picture below)

enter image description here

The data points connected by the purple line are examples of problem cases, data observed at ~5 seconds and ~110 seconds would be forced to a time of ~100 seconds after transformation.

Question

Therefore, I would like to know if there is a way to force the function maximum (or minimum) to X = 0? I am also open to other suggestions to bypass this problem (currently, I am ignoring the left half of the polynomial as a temporary dirty hack/fix).

Additional information

Removing the b*x part of the fit function is not a possibility as this function should be able to return a (near) linear fit as well, see the below plot

enter image description here

Bas Jansen
  • 3,273
  • 5
  • 30
  • 66
  • 1
    If "near-linear" and quadratic results are both legitimate possibilities, I suspect you are looking for some sort of empirical fit. Perhaps a power law would be a better model: `a*x**b + c`. This includes the possibilities of a parabola (`b` is 2), and a line (`b` is 1). – Warren Weckesser Aug 10 '15 at 15:01
  • 1
    You do not pass the parameter c to fitFunc; is that on purpose? You can add the point (0,0) to your data and then use a high weight for this point. I show something similar for R [here.](http://stackoverflow.com/questions/31837610/forcing-nls-to-fit-a-curve-passing-through-a-specified-point/31888068#31888068) If you provide all your data, I could try to do this for Python as well which should not be too difficult; you then pass 'sigma' in the curve_fit function: [doc](http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.optimize.curve_fit.html). – Cleb Aug 10 '15 at 16:12
  • Possible duplicate of http://stackoverflow.com/questions/16541171/how-do-i-put-a-constraint-on-scipy-curve-fit – Daniel Renshaw Aug 10 '15 at 16:28
  • @Cleb The omission of `c` is an error on mine part when writing the question here. Furthermore, I will attach the coordinates that I used in both example segments. – Bas Jansen Aug 10 '15 at 16:41
  • @WarrenWeckesser I will accept your answer on using power law if you write one, that indeed achieved everything that I wanted. – Bas Jansen Aug 10 '15 at 17:09

1 Answers1

1

If "near-linear" and quadratic results are both legitimate possibilities, I suspect you are looking for some sort of empirical fit. Perhaps a power law would be a better model: a*x**b + c. This includes the possibilities of a parabola (b is 2), and a line (b is 1)

Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214