Esempio n. 1
0
def poly_lsq(x, y, n, verbose=False, itmax=200):
    ''' Performs a polynomial least squares fit to the data,
    with errors! Uses scipy odrpack, but for least squares.

    IN:
       x,y (arrays) - data to fit
       n (int)      - polinomial order
       verbose      - can be 0,1,2 for different levels of output
                      (False or True are the same as 0 or 1)
       itmax (int)  - optional maximum number of iterations

    OUT:
       coeff -  polynomial coefficients, lowest order first
       err   - standard error (1-sigma) on the coefficients

    --Tiago, 20071114
    '''
    func = models.polynomial(n)
    mydata = odr.Data(x, y)
    myodr = odr.ODR(mydata, func, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
    if fit.stopreason[0] == 'Iteration limit reached':
        print('(WWW) poly_lsq: Iteration limit reached, result not reliable!')
    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    return coeff, err
Esempio n. 2
0
def gaussian_lsq(x, y, verbose=False, itmax=200, iparams=[]):
    ''' Performs a gaussian least squares fit to the data,
    with errors! Uses scipy odrpack, but for least squares.'''
    def _gauss_fjd(B, x):
        # Analytical derivative of gaussian with respect to x
        return 2 * (x - B[0]) * gaussian(B, x)

    # these derivatives need to be fixed!
    def _gauss_fjb(B, x):
        # Analytical derivatives of gaussian with respect to parameters
        _ret = np.concatenate(
            (-2 * (x - B[0]) * gaussian(B, x),
             ((x - B[0])**2 / (2 * B[1]**2) - 1) / B[1] * gaussian(B, x),
             gaussian(B, x) / B[2], np.ones(x.shape, float)))
        _ret.shape = (4, ) + x.shape
        return _ret

    # Centre data in mean(x) (makes better conditioned matrix)
    mx = np.mean(x)
    x2 = x - mx

    if not any(iparams):
        # automatic guessing of gaussian's initial parameters (saves
        # iterations)
        iparams = np.array([
            x2[np.argmax(y)],
            np.std(y),
            math.sqrt(2 * math.pi) * np.std(y) * np.max(y), 1.
        ])

    gauss = odr.Model(gaussian, fjacd=_gauss_fjd, fjacb=_gauss_fjb)

    mydata = odr.Data(x2, y)
    myodr = odr.ODR(mydata, gauss, beta0=iparams, maxit=itmax)

    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)

    fit = myodr.run()

    # Display results:
    if verbose:
        fit.pprint()
        print('Re-centered Beta: [%f  %f  %f %f]' %
              (fit.beta[0] + mx, fit.beta[1], fit.beta[2], fit.beta[3]))

    itlim = False
    if fit.stopreason[0] == 'Iteration limit reached':
        itlim = True
        print("(WWW) gauss_lsq: Iteration limit reached, result not reliable!")

    # Results and errors
    coeff = fit.beta
    coeff[0] += mx  # Recentre in original axis
    err = fit.sd_beta

    return coeff, err, itlim
Esempio n. 3
0
def double_gauss_lsq(x, y, verbose=False, itmax=200, iparams=[]):
    ''' Performs a double gaussian least squares fit to the data,
    with errors! Uses scipy odrpack, but for least squares.'''
    def _dgauss_fjd(B, x):
        # Analytical derivative of gaussian with respect to x
        return (B[0] - x) / B[1]**2 * gaussian(np.concatenate((B[:3], [0.])), x) + \
               (B[3] - x) / B[4]**2 * gaussian(np.concatenate((B[3:6], [0.])), x)

    def _dgauss_fjb(B, x):
        # Analytical derivatives of gaussian with respect to parameters
        gauss1 = gaussian(np.concatenate((B[:3], [0.])), x)
        gauss2 = gaussian(np.concatenate((B[3:6], [0.])), x)
        _ret = np.concatenate(
            ((x - B[0]) / B[1]**2 * gauss1,
             ((B[0] - x)**2 - B[1]**2) / B[1]**3 * gauss1, gauss1 / B[2],
             (x - B[3]) / B[4]**2 * gauss2,
             ((B[3] - x)**2 - B[4]**2) / B[4]**3 * gauss2, gauss2 / B[5],
             np.ones(x.shape, float)))
        _ret.shape = (7, ) + x.shape
        return _ret

    # Centre data in mean(x) (makes better conditioned matrix)
    mx = mean(x)
    x2 = x - mx
    if not any(iparams):
        iparams = array([
            x2[np.argmax(y)],
            np.std(y),
            np.sqrt(2 * np.pi) * np.std(y) * max(y), x2[np.argmax(y)],
            np.std(y),
            np.sqrt(2 * np.pi) * np.std(y) * max(y), 1.
        ])
    dgauss = odr.Model(double_gaussian, fjacd=_dgauss_fjd, fjacb=_dgauss_fjb)
    mydata = odr.Data(x2, y)
    myodr = odr.ODR(mydata, dgauss, beta0=iparams, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
        print('Re-centered Beta: [%f  %f  %f  %f  %f  %f  %f]' %
              (fit.beta[0] + mx, fit.beta[1], fit.beta[2], fit.beta[3] + mx,
               fit.beta[4], fit.beta[5], fit.beta[6]))
    itlim = False
    if fit.stopreason[0] == 'Iteration limit reached':
        itlim = True
        print('(WWW) gauss_lsq: Iteration limit reached, result not reliable!')
    # Results and errors
    coeff = fit.beta
    coeff[[0, 3]] += mx  # Recentre in original axis
    err = fit.sd_beta
    return coeff, err, itlim
Esempio n. 4
0
 def fit(self, num_cuts, truncate=True, withSpreadterm=False):
     x, y, xaxis, m, s, cnt = CMECostModel.qc(self, num_cuts, truncate)
     try:
         popt, pcov = curve_fit(self.model_curve_guess, x, y)
     except RuntimeError:
         popt = [1.0] * CMECostModel.num_free_params
     func = odr.Model(self.model_curve_ODR)
     odrdata = odr.Data(x, y)
     odrmodel = odr.ODR(odrdata, func, beta0=popt, maxit=500, ifixx=[0])
     o = odrmodel.run()
     return o, x, y, xaxis, m, s, cnt
def fitTrack(trackArray):
    results = []
    x = []
    y = []
    energy = []
    for i in trackArray:
        x.append(i[0])
        y.append(i[1])
        energy.append(i[2])
    slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
    mydata = odrpack.Data(x, y, energy, energy)
    linear = odrpack.Model(f)
    myodr = odrpack.ODR(mydata, linear, beta0=[slope, intercept])
    myoutput = myodr.run()
    results.append(myoutput.beta)
    return results
def minThis(vertex, trackArray):
    sumOfSquares = 0
    for i in range(len(trackArray)):
        x = []
        y = []
        energy = []
        #print trackArray
        for i in trackArray[i]:
            x.append(i[0])
            y.append(i[1])
            energy.append(i[2])
        slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
        mydata = odrpack.Data(x, y, energy, energy)
        linear = odrpack.Model(fv, extra_args=vertex)
        myodr = odrpack.ODR(mydata, linear, beta0=[slope, intercept])
        myoutput = myodr.run()
        sumOfSquares += myoutput.sum_square
    return sumOfSquares
Esempio n. 7
0
def poly_lsq(x, y, n, verbose=False, itmax=200):
    """
    Performs a polynomial least squares fit to the data,
    with errors! Uses scipy odrpack, but for least squares.

    Parameters
    ----------
    x, y : 1-D arrays
        Data to fit.
    n : int
        Polynomial order
    verbose : bool or int, optional
        Can be 0,1,2 for different levels of output (False or True
        are the same as 0 or 1)
    itmax : int, optional
        Maximum number of iterations.

    Returns
    -------
    coeff :  1-D array
        Polynomial coefficients, lowest order first.
    err :  1-D array
        Standard error (1-sigma) on the coefficients.
    """
    func = models.polynomial(n)
    mydata = odr.Data(x, y)
    myodr = odr.ODR(mydata, func, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
    if fit.stopreason[0] == 'Iteration limit reached':
        print('(WWW) poly_lsq: Iteration limit reached, result not reliable!')
    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    return coeff, err
Esempio n. 8
0
def estimate_spatial_resolution(x,
                                y,
                                ofunc=blurred_step_function,
                                beta0=None,
                                verbose=True):
    """
    Estimate the spatial resolution of an X-ray image from a lineout of an edge.
    It assumes that if the spatial resolution was ideal, that should produce a sharp step.
    Instead we have a step convolved with a gaussian function. This function then estimates 
    the standard deviation of this gaussian. 

    Parameters
    ----------
        x : ndarray : position in physical units [µm, cm, etc]
        y : ndarray : signal on the IP
        ofunc: objective function, here the convolution of a step with a gaussian
        beta0 : initial estimate of parameters. A good estimate could be for instance, 
                   beta0 = [y.mean(), x.mean(), 20, y.mean(), 0]
        verbose: true


    Returns
    -------
      tuple:  (std, std_err)
    """
    from scipy import odr
    mmodel = odr.Model(ofunc)
    mdata = odr.Data(x, y)

    fit = odr.ODR(mdata, mmodel, beta0, maxit=1000)
    fit.set_job(fit_type=2)  # least squares
    fit.set_iprint(final=verbose)
    fit.run()
    beta = fit.output.beta
    error = fit.output.sd_beta

    return beta, error
Esempio n. 9
0
def circle_lsq(x, y, up=True, verbose=False, itmax=200, iparams=[]):
    ''' Method to compute a circle fit, It fits for circle
    parameters in the form y = B_2 +/- sqrt(B_0^2-(x-B_1)^2), the sign
    is negative if up is False.

    IN:
       x,y (arr)     - data to fit
       n (int)       - polinomial order
       verbose       - can be 0,1,2 for different levels of output
                         (False or True are the same as 0 or 1)
       itmax (int)   - optional maximum number of iterations.
       iparams (arr) - optional initial parameters b0,b1,b2

    OUT:
       coeff -  polynomial coefficients, lowest order first
       err   - standard error (1-sigma) on the coefficients

    --Tiago, 20080120
    '''

    # circle functions for B=r,x0,y0
    def circle_up(B, x):
        return B[2] + sqrt(B[0]**2 - (x - B[1])**2)

    def circle_dn(B, x):
        return B[2] - sqrt(B[0]**2 - (x - B[1])**2)

    # Derivative of function in respect to x
    def circle_fjd_up(B, x):
        return -(x - B[1]) / (sqrt(B[0]**2 - (x - B[1])**2))

    def circle_fjd_dn(B, x):
        return (x - B[1]) / (sqrt(B[0]**2 - (x - B[1])**2))

    # Derivative of function in respect to B[i]
    def circle_fjb_up(B, x):
        _ret = np.concatenate((
            B[0] / (sqrt(B[0]**2 - (x - B[1])**2)),
            -circle_fjd_up(B, x),
            np.ones(x.shape, float),
        ))
        _ret.shape = (3, ) + x.shape
        return _ret

    def circle_fjb_dn(B, x):
        _ret = np.concatenate((
            B[0] / (sqrt(B[0]**2 - (x - B[1])**2)),
            -circle_fjd_dn(B, x),
            np.ones(x.shape, float),
        ))
        _ret.shape = (3, ) + x.shape
        return _ret

    if any(iparams):

        def circle_est(data):
            return tuple(iparams)
    else:

        def circle_est(data):
            return (1., 1., 1.)

    if up:
        circle_fit = odr.Model(circle_up,
                               fjacd=circle_fjd_up,
                               fjacb=circle_fjb_up,
                               estimate=circle_est)
    else:
        circle_fit = odr.Model(circle_dn,
                               fjacd=circle_fjd_dn,
                               fjacb=circle_fjb_dn,
                               estimate=circle_est)
    mydata = odr.Data(x, y)
    myodr = odr.ODR(mydata, circle_fit, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
    if fit.stopreason[0] != 'Sum of squares convergence':
        if verbose:
            print('(WWW): circle_lsq: fit result not reliable')
        success = 0
    else:
        success = 1
    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    return coeff, success, err
Esempio n. 10
0
def gauss_lsq(x,
              y,
              weight_x=1.,
              weight_y=1.,
              verbose=False,
              itmax=200,
              iparams=[]):
    """
    Performs a Gaussian least squares fit to the data,
    with errors! Uses scipy odrpack, but for least squares.

    Parameters
    ----------
    x : 1D array-like
        Observed data, independent variable
    y : 1D array-like
        Observed data, dependent variable
    weight_x: array-like, optional
        Weights for independent variable. This is typically based on the errors,
        if any. With errors, normal weights should be 1/err**2. If weight is a
        scalar, the same weight will be used for all points and therefore its
        value is irrelevant.
    weight_y: array-like, optional.
        Weights for independent variable. This is typically based on the errors,
        if any. With errors, normal weights should be 1/err**2. For Poisson
        weighing, should be 1/y.
    verbose: boolean
        If True, will print out more detailed information about the result.
    itmax: integer, Optional
        Maximum number of iterations, default is 200.
    iparams: list, optional
        Starting guess of Gaussian parameters. Optional but highly recommended
        to use realistic values!

    Returns
    -------
    output: tuple
        Tuple with containing (coeff, err, itlim), where coeff are the fit
        resulting coefficients (same order as Gaussian function above), err are
        the errors on each coefficient, and itlim is the number of iterations.

    Notes
    -----
    See documentation of scipy.odr.ordpack for more information.
    """
    def _gauss_fjd(B, x):
        # Analytical derivative of gaussian with respect to x
        return (B[0] - x) / B[1]**2 * gaussian(np.concatenate(
            (B[:3], [0.])), x)

    def _gauss_fjb(B, x):
        gauss1 = gaussian(np.concatenate((B[:3], [0.])), x)
        # Analytical derivatives of gaussian with respect to parameters
        _ret = np.concatenate(
            ((x - B[0]) / B[1]**2 * gauss1,
             ((B[0] - x)**2 - B[1]**2) / B[1]**3 * gauss1, gauss1 / B[2],
             np.ones(x.shape, float)))
        _ret.shape = (4, ) + x.shape
        return _ret

    # Centre data in mean(x) (makes better conditioned matrix)
    mx = np.mean(x)
    x2 = x - mx
    if not any(iparams):
        iparams = np.array([
            x2[np.argmax(y)],
            np.std(y),
            np.sqrt(2 * np.pi) * np.std(y) * max(y), 1.
        ])
    gauss = odr.Model(gaussian, fjacd=_gauss_fjd, fjacb=_gauss_fjb)
    mydata = odr.Data(x2, y, wd=weight_x, we=weight_y)
    myodr = odr.ODR(mydata, gauss, beta0=iparams, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
        print('Re-centered Beta: [%f  %f  %f %f]' %
              (fit.beta[0] + mx, fit.beta[1], fit.beta[2], fit.beta[3]))
    itlim = False
    if fit.stopreason[0] == 'Iteration limit reached':
        itlim = True
        print('(WWW) gauss_lsq: Iteration limit reached, result not reliable!')
    # Results and errors
    coeff = fit.beta
    coeff[0] += mx  # Recentre in original axis
    err = fit.sd_beta
    return coeff, err, itlim
Esempio n. 11
0
def quad_lsq(x, y, verbose=False, itmax=200, iparams=[]):
    ''' Method to compute a parabola fit, more handy as it fits for
    parabola parameters in the form y = B_0 * (x - B_1)**2 + B_2.
    This is computationally slower than poly_lsq, so beware of its usage
    for time consuming operations.

    IN:
       x,y (arr)     - data to fit
       n (int)       - polinomial order
       verbose       - can be 0,1,2 for different levels of output
                         (False or True are the same as 0 or 1)
       itmax (int)   - optional maximum number of iterations.
       iparams (arr) - optional initial parameters b0,b1,b2

    OUT:
       coeff -  polynomial coefficients, lowest order first
       err   - standard error (1-sigma) on the coefficients


    --Tiago, 20071115
    '''

    # Tiago's internal new definition of quadratic
    def _quadratic(B, x):
        return B[0] * (x - B[1]) * (x - B[1]) + B[2]

    def _quad_fjd(B, x):
        return 2 * B[0] * (x - B[1])

    def _quad_fjb(B, x):
        _ret = np.concatenate((
            np.ones(x.shape, float),
            2 * B[0] * (B[1] - x),
            x * x - 2 * B[1] * x + B[1] * B[1],
        ))
        _ret.shape = (3, ) + x.shape
        return _ret

    if any(iparams):

        def _quad_est(data):
            return tuple(iparams)
    else:

        def _quad_est(data):
            return (1., 1., 1.)

    quadratic = odr.Model(_quadratic,
                          fjacd=_quad_fjd,
                          fjacb=_quad_fjb,
                          estimate=_quad_est)
    mydata = odr.Data(x, y)
    myodr = odr.ODR(mydata, quadratic, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
    if fit.stopreason[0] == 'Iteration limit reached':
        print('(WWW) quad_lsq: iteration limit reached, result not reliable!')
    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    return coeff, err
Esempio n. 12
0
def circle_lsq(x, y, up=True, verbose=False, itmax=200, iparams=[]):
    """
    Method to compute a (half) circle fit, It fits for circle
    parameters in the form y = B_2 +/- sqrt(B_0^2 - (x - B_1)^2), the sign
    is negative if up is False.

    Parameters
    ----------
    x, y : 1-D arrays
        Data to fit.
    up : bool, optional
        Whether the half circle is up or down.
    verbose : bool or int, optional
        Can be 0,1,2 for different levels of output (False or True
        are the same as 0 or 1)
    itmax : int, optional
        Maximum number of iterations.
    iparams : 1D array, optional
        Initial parameters B_0, B_1, B_2.

    Returns
    -------
    coeff :  1-D array
        Parabola coefficients
    err :  1-D array
        Standard error (1-sigma) on the coefficients.
    """

    # circle functions for B=r,x0,y0
    def circle_up(B, x):
        return B[2] + sqrt(B[0]**2 - (x - B[1])**2)

    def circle_dn(B, x):
        return B[2] - sqrt(B[0]**2 - (x - B[1])**2)

    # Derivative of function in respect to x
    def circle_fjd_up(B, x):
        return -(x - B[1]) / (sqrt(B[0]**2 - (x - B[1])**2))

    def circle_fjd_dn(B, x):
        return (x - B[1]) / (sqrt(B[0]**2 - (x - B[1])**2))

    # Derivative of function in respect to B[i]
    def circle_fjb_up(B, x):
        _ret = np.concatenate((
            B[0] / (sqrt(B[0]**2 - (x - B[1])**2)),
            -circle_fjd_up(B, x),
            np.ones(x.shape, float),
        ))
        _ret.shape = (3, ) + x.shape
        return _ret

    def circle_fjb_dn(B, x):
        _ret = np.concatenate((
            B[0] / (sqrt(B[0]**2 - (x - B[1])**2)),
            -circle_fjd_dn(B, x),
            np.ones(x.shape, float),
        ))
        _ret.shape = (3, ) + x.shape
        return _ret

    if any(iparams):

        def circle_est(data):
            return tuple(iparams)
    else:

        def circle_est(data):
            return (1., 1., 1.)

    if up:
        circle_fit = odr.Model(circle_up,
                               fjacd=circle_fjd_up,
                               fjacb=circle_fjb_up,
                               estimate=circle_est)
    else:
        circle_fit = odr.Model(circle_dn,
                               fjacd=circle_fjd_dn,
                               fjacb=circle_fjb_dn,
                               estimate=circle_est)
    mydata = odr.Data(x, y)
    myodr = odr.ODR(mydata, circle_fit, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
    if fit.stopreason[0] != 'Sum of squares convergence':
        if verbose:
            print('(WWW): circle_lsq: fit result not reliable')
        success = 0
    else:
        success = 1
    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    return coeff, success, err
Esempio n. 13
0
def quad_lsq(x, y, verbose=False, itmax=200, iparams=[]):
    """
    Fits a parabola to the data, more handy as it fits for
    parabola parameters in the form y = B_0 * (x - B_1)**2 + B_2.
    This is computationally slower than poly_lsq, so beware of its usage
    for time consuming operations. Uses scipy odrpack, but for least squares.

    Parameters
    ----------
    x, y : 1-D arrays
        Data to fit.
    verbose : bool or int, optional
        Can be 0,1,2 for different levels of output (False or True
        are the same as 0 or 1)
    itmax : int, optional
        Maximum number of iterations.
    iparams : 1D array, optional
        Initial parameters B_0, B_1, B_2.

    Returns
    -------
    coeff :  1-D array
        Parabola coefficients
    err :  1-D array
        Standard error (1-sigma) on the coefficients.
    """

    # Internal definition of quadratic
    def _quadratic(B, x):
        return B[0] * (x - B[1]) * (x - B[1]) + B[2]

    def _quad_fjd(B, x):
        return 2 * B[0] * (x - B[1])

    def _quad_fjb(B, x):
        _ret = np.concatenate((
            np.ones(x.shape, float),
            2 * B[0] * (B[1] - x),
            x * x - 2 * B[1] * x + B[1] * B[1],
        ))
        _ret.shape = (3, ) + x.shape
        return _ret

    if any(iparams):

        def _quad_est(data):
            return tuple(iparams)
    else:

        def _quad_est(data):
            return (1., 1., 1.)

    quadratic = odr.Model(_quadratic,
                          fjacd=_quad_fjd,
                          fjacb=_quad_fjb,
                          estimate=_quad_est)
    mydata = odr.Data(x, y)
    myodr = odr.ODR(mydata, quadratic, maxit=itmax)
    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2:
        myodr.set_iprint(final=2)
    fit = myodr.run()
    # Display results:
    if verbose:
        fit.pprint()
    if fit.stopreason[0] == 'Iteration limit reached':
        print('(WWW) quad_lsq: iteration limit reached, result not reliable!')
    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    return coeff, err
Esempio n. 14
0
def fit(func,
        x,
        y,
        default_pars=None,
        data_range=None,
        we=None,
        verbose=False,
        itmax=200):
    ''' The meat of the fitting package. See docs of fit.py for more details.
  Functions available are gaus and expo and more.

  Error implementation provided via an example by: Tiago, 20071114

  Performs a least squares fit to the data, with errors!
  Uses scipy odrpack, but for least squares.
  
  IN: (func, x, y, verbose, itmax)
     func         - A function that accepts input in the form:
                    func(params, x)
     x,y (arrays) - data to fit
     default_pars - Optional default parameters to start minimization at.
     data_range   - Fit a subrange of (x,y). Provide a tuple of the form
                    (x_min, x_max).
     we           - Weighting for data points as delivered to ODR. You
                    probably want it the same length as x.
     verbose      - can be 0,1,2 for different levels of output
                    (False or True are the same as 0 or 1)
     itmax (int)  - optional maximum number of iterations
     
  OUT: (fit, params, err)
     fit    -  xfit,yfit arrays that can immediately plotted to see the
              results of your fit. xf and yf are defined as: 
                  xfit = linspace( min(x), max(x), len(x)*10)
                  yfit = func(xfit)
     params - the coefficients of your fit in the order the function takes.
     err    - standard error (1-sigma) on the coefficients

  '''

    # If this is a histogram output, correct it for the user.
    if len(x) == len(y) + 1:
        x = (x[1:] + x[:-1]) / 2.
    # Take a slice of data.
    if data_range:
        y = y[logical_and(x > data_range[0], x < data_range[1])]
        x = x[logical_and(x > data_range[0], x < data_range[1])]

    # http://www.scipy.org/doc/api_docs/SciPy.odr.odrpack.html
    # see models.py and use ready made models!!!!
    if default_pars != None:
        beta0 = array(default_pars)
    else:
        beta0 = get_default_params(x, y, func)
    model_func = models.Model(func)

    mydata = odr.Data(x, y, we)
    myodr = odr.ODR(mydata, model_func, maxit=itmax, beta0=beta0)

    # Set type of fit to least-squares:
    myodr.set_job(fit_type=2)
    if verbose == 2: myodr.set_iprint(final=2)

    fit = myodr.run()

    # Display results:
    if verbose: fit.pprint()

    if fit.stopreason[0] == 'Iteration limit reached':
        print('(WWW) poly_lsq: Iteration limit reached, result not reliable!')

    # Results and errors
    coeff = fit.beta
    err = fit.sd_beta
    chi = fit.sum_square

    # The resulting fit.
    xfit = linspace(min(x), max(x), len(x) * 10)
    yfit = func(fit.beta, xfit)

    return array([xfit, yfit]), coeff, err, chi