def fit_mod(fc=0.01, mmax = 1e7):
    t0 = 0.1
    delta_t = 0.5
    mmin = log10(200.)
    age_slope = -0.9
    cmf_slope = -2.0
    starting = array([t0, delta_t, mmin, cmf_slope,  age_slope])
    parinfo = [{'value':0., 'fixed':0, 'limited':[0,0], 'limits':[0.,0.], \
                'step':0.} 
                                                for i in range(5)]
    fac = 0.5
    print starting
    parinfo[0]['limited'][0]=1
    parinfo[0]['limited'][1]=1
    parinfo[0]['limits'][0]=0.
    parinfo[0]['limits'][1]=10.
    parinfo[0]['value']=0.1
    parinfo[0]['step']=0.01*fac

    parinfo[1]['limited'][0]=1
    parinfo[1]['limited'][1]=1
    parinfo[1]['limits'][0]=0.
    parinfo[1]['limits'][1]=10.
    parinfo[1]['value']=0.5
    parinfo[1]['step']=0.01*fac

    parinfo[2]['limited'][0]=1
    parinfo[2]['limited'][1]=1
    parinfo[2]['limits'][0]=2.
    parinfo[2]['limits'][1]=4.
    parinfo[2]['value']=2.2
    parinfo[2]['step']=0.01*fac
    
    parinfo[3]['limited'][0]=1
    parinfo[3]['limited'][1]=1
    parinfo[3]['limits'][0]=-2.2
    parinfo[3]['limits'][1]=-1.8
    parinfo[3]['value']=-2.
    parinfo[3]['step']=0.01*fac
    
    parinfo[4]['limited'][0]=1
    parinfo[4]['limited'][1]=1
    parinfo[4]['limits'][0]=-0.2
    parinfo[4]['limits'][1]=0.2
    parinfo[4]['value']=0
    parinfo[4]['step']=0.01*fac
    
    sss = call_wrap2(starting)
    return mpfit(call_wrap2, parinfo = parinfo, \
                    functkw={'mmax':mmax, 'fc':fc})
def multigaussfit(xax,
                  data,
                  ngauss=1,
                  err=None,
                  params=[1, 0, 1],
                  fixed=[False, False, False],
                  limitedmin=[False, False, True],
                  limitedmax=[False, False, False],
                  minpars=[0, 0, 0],
                  maxpars=[0, 0, 0],
                  quiet=True,
                  shh=True):
    """
    An improvement on onedgaussfit.  Lets you fit multiple gaussians.

    Inputs:
       xax - x axis
       data - y axis
       ngauss - How many gaussians to fit?  Default 1 (this could supercede onedgaussfit)
       err - error corresponding to data

     These parameters need to have length = 3*ngauss.  If ngauss > 1 and length = 3, they will
     be replicated ngauss times, otherwise they will be reset to defaults:
       params - Fit parameters: [amplitude, offset, width] * ngauss
              If len(params) % 3 == 0, ngauss will be set to len(params) / 3
       fixed - Is parameter fixed?
       limitedmin/minpars - set lower limits on each parameter (default: width>0)
       limitedmax/maxpars - set upper limits on each parameter

       quiet - should MPFIT output each iteration?
       shh - output final parameters?

    Returns:
       Fit parameters
       Model
       Fit errors
       chi2
    """

    if len(params) != ngauss and (len(params) / 3) > ngauss:
        ngauss = len(params) / 3

    # make sure all various things are the right length; if they're not, fix them using the defaults
    for parlist in (params, fixed, limitedmin, limitedmax, minpars, maxpars):
        if len(parlist) != 3 * ngauss:
            # if you leave the defaults, or enter something that can be multiplied by 3 to get to the
            # right number of gaussians, it will just replicate
            if len(parlist) == 3:
                parlist *= ngauss
            elif parlist == params:
                parlist[:] = [1, 0, 1] * ngauss
            elif parlist == fixed or parlist == limitedmax:
                parlist[:] = [False, False, False] * ngauss
            elif parlist == limitedmin:
                parlist[:] = [False, False, True] * ngauss
            elif parlist == minpars or parlist == maxpars:
                parlist[:] = [0, 0, 0] * ngauss

    def mpfitfun(x, y, err):
        if err == None:

            def f(p, fjac=None):
                return [0, (y - n_gaussian(pars=p)(x))]
        else:

            def f(p, fjac=None):
                return [0, (y - n_gaussian(pars=p)(x)) / err]

        return f

    if xax == None:
        xax = numpy.arange(len(data))

    parnames = {0: "SHIFT", 1: "WIDTH", 2: "AMPLITUDE"}

    parinfo = [{
        'n': ii,
        'value': params[ii],
        'limits': [minpars[ii], maxpars[ii]],
        'limited': [limitedmin[ii], limitedmax[ii]],
        'fixed': fixed[ii],
        'parname': parnames[ii / 3] + str(ii / 3),
        'error': ii
    } for ii in range(len(params))]

    mp = mpfit(mpfitfun(xax, data, err), parinfo=parinfo, quiet=quiet)
    mpp = mp.params
    mpperr = mp.perror
    chi2 = mp.fnorm

    if mp.status == 0:
        raise Exception(mp.errmsg)

    if not shh:
        for i, p in enumerate(mpp):
            parinfo[i]['value'] = p
            print(parinfo[i]['parname'], p, " +/- ", mpperr[i])
        print("Chi2: ", mp.fnorm, " Reduced Chi2: ", mp.fnorm / len(data),
              " DOF:",
              len(data) - len(mpp))

    return mpp, n_gaussian(pars=mpp)(xax), mpperr, chi2
def onedgaussfit(xax,
                 data,
                 err=None,
                 params=[0, 1, 0, 1],
                 fixed=[False, False, False, False],
                 limitedmin=[False, False, False, True],
                 limitedmax=[False, False, False, False],
                 minpars=[0, 0, 0, 0],
                 maxpars=[0, 0, 0, 0],
                 quiet=True,
                 shh=True):
    """
    Inputs:
       xax - x axis
       data - y axis
       err - error corresponding to data

       params - Fit parameters: Height of background, Amplitude, Shift, Width
       fixed - Is parameter fixed?
       limitedmin/minpars - set lower limits on each parameter (default: width>0)
       limitedmax/maxpars - set upper limits on each parameter
       quiet - should MPFIT output each iteration?
       shh - output final parameters?

    Returns:
       Fit parameters
       Model
       Fit errors
       chi2
    """
    def mpfitfun(x, y, err):
        if err == None:

            def f(p, fjac=None):
                return [0, (y - onedgaussian(x, *p))]
        else:

            def f(p, fjac=None):
                return [0, (y - onedgaussian(x, *p)) / err]

        return f

    if xax == None:
        xax = numpy.arange(len(data))

    parinfo = [{
        'n': 0,
        'value': params[0],
        'limits': [minpars[0], maxpars[0]],
        'limited': [limitedmin[0], limitedmax[0]],
        'fixed': fixed[0],
        'parname': "HEIGHT",
        'error': 0
    }, {
        'n': 1,
        'value': params[1],
        'limits': [minpars[1], maxpars[1]],
        'limited': [limitedmin[1], limitedmax[1]],
        'fixed': fixed[1],
        'parname': "AMPLITUDE",
        'error': 0
    }, {
        'n': 2,
        'value': params[2],
        'limits': [minpars[2], maxpars[2]],
        'limited': [limitedmin[2], limitedmax[2]],
        'fixed': fixed[2],
        'parname': "SHIFT",
        'error': 0
    }, {
        'n': 3,
        'value': params[3],
        'limits': [minpars[3], maxpars[3]],
        'limited': [limitedmin[3], limitedmax[3]],
        'fixed': fixed[3],
        'parname': "WIDTH",
        'error': 0
    }]

    mp = mpfit(mpfitfun(xax, data, err), parinfo=parinfo, quiet=quiet)
    mpp = mp.params
    mpperr = mp.perror
    chi2 = mp.fnorm

    if mp.status == 0:
        raise Exception(mp.errmsg)

    if not shh:
        for i, p in enumerate(mpp):
            parinfo[i]['value'] = p
            print(parinfo[i]['parname'], p, " +/- ", mpperr[i])
        print("Chi2: ", mp.fnorm, " Reduced Chi2: ", mp.fnorm / len(data),
              " DOF:",
              len(data) - len(mpp))

    return mpp, onedgaussian(xax, *mpp), mpperr, chi2
def gaussfit(data,
             err=None,
             params=[],
             autoderiv=1,
             return_all=0,
             circle=0,
             fixed=numpy.repeat(False, 7),
             limitedmin=[False, False, False, False, True, True, True],
             limitedmax=[False, False, False, False, False, False, True],
             usemoment=numpy.array([], dtype='bool'),
             minpars=numpy.repeat(0, 7),
             maxpars=[0, 0, 0, 0, 0, 0, 360],
             rotate=1,
             vheight=1,
             quiet=True,
             returnmp=False,
             returnfitimage=False,
             **kwargs):
    """
    Gaussian fitter with the ability to fit a variety of different forms of
    2-dimensional gaussian.
    
    Input Parameters:
        data - 2-dimensional data array
        err=None - error array with same size as data array
        params=[] - initial input parameters for Gaussian function.
            (height, amplitude, x, y, width_x, width_y, rota)
            if not input, these will be determined from the moments of the system, 
            assuming no rotation
        autoderiv=1 - use the autoderiv provided in the lmder.f function (the
            alternative is to us an analytic derivative with lmdif.f: this method
            is less robust)
        return_all=0 - Default is to return only the Gaussian parameters.  
                   1 - fit params, fit error
        returnfitimage - returns (best fit params,best fit image)
        returnmp - returns the full mpfit struct
        circle=0 - default is an elliptical gaussian (different x, y widths),
            but can reduce the input by one parameter if it's a circular gaussian
        rotate=1 - default allows rotation of the gaussian ellipse.  Can remove
            last parameter by setting rotate=0.  numpy.expects angle in DEGREES
        vheight=1 - default allows a variable height-above-zero, i.e. an
            additive constant for the Gaussian function.  Can remove first
            parameter by setting this to 0
        usemoment - can choose which parameters to use a moment estimation for.
            Other parameters will be taken from params.  Needs to be a boolean
            array.

    Output:
        Default output is a set of Gaussian parameters with the same shape as
            the input parameters

        Can also output the covariance matrix, 'infodict' that contains a lot
            more detail about the fit (see scipy.optimize.leastsq), and a message
            from leastsq telling what the exit status of the fitting routine was

        Warning: Does NOT necessarily output a rotation angle between 0 and 360 degrees.
    """
    usemoment = numpy.array(usemoment, dtype='bool')
    params = numpy.array(params, dtype='float')
    if usemoment.any() and len(params) == len(usemoment):
        moment = numpy.array(moments(data, circle, rotate, vheight, **kwargs),
                             dtype='float')
        params[usemoment] = moment[usemoment]
    elif params == [] or len(params) == 0:
        params = (moments(data, circle, rotate, vheight, **kwargs))
    if vheight == 0:
        vheight = 1
        params = numpy.concatenate([[0], params])
        fixed[0] = 1

    # mpfit will fail if it is given a start parameter outside the allowed range:
    for i in range(len(params)):
        if params[i] > maxpars[i] and limitedmax[i]: params[i] = maxpars[i]
        if params[i] < minpars[i] and limitedmin[i]: params[i] = minpars[i]

    if err == None:
        errorfunction = lambda p: numpy.ravel((twodgaussian(p,circle,rotate,vheight)\
                (*numpy.indices(data.shape)) - data))
    else:
        errorfunction = lambda p: numpy.ravel((twodgaussian(p,circle,rotate,vheight)\
                (*numpy.indices(data.shape)) - data)/err)

    def mpfitfun(data, err):
        if err == None:

            def f(p, fjac=None):                return [0,numpy.ravel(data-twodgaussian(p,circle,rotate,vheight)\
    (*numpy.indices(data.shape)))]
        else:

            def f(p, fjac=None):                return [0,numpy.ravel((data-twodgaussian(p,circle,rotate,vheight)\
    (*numpy.indices(data.shape)))/err)]

        return f

    parinfo = [{
        'n': 1,
        'value': params[1],
        'limits': [minpars[1], maxpars[1]],
        'limited': [limitedmin[1], limitedmax[1]],
        'fixed': fixed[1],
        'parname': "AMPLITUDE",
        'error': 0
    }, {
        'n': 2,
        'value': params[2],
        'limits': [minpars[2], maxpars[2]],
        'limited': [limitedmin[2], limitedmax[2]],
        'fixed': fixed[2],
        'parname': "XSHIFT",
        'error': 0
    }, {
        'n': 3,
        'value': params[3],
        'limits': [minpars[3], maxpars[3]],
        'limited': [limitedmin[3], limitedmax[3]],
        'fixed': fixed[3],
        'parname': "YSHIFT",
        'error': 0
    }, {
        'n': 4,
        'value': params[4],
        'limits': [minpars[4], maxpars[4]],
        'limited': [limitedmin[4], limitedmax[4]],
        'fixed': fixed[4],
        'parname': "XWIDTH",
        'error': 0
    }]
    if vheight == 1:
        parinfo.insert(
            0, {
                'n': 0,
                'value': params[0],
                'limits': [minpars[0], maxpars[0]],
                'limited': [limitedmin[0], limitedmax[0]],
                'fixed': fixed[0],
                'parname': "HEIGHT",
                'error': 0
            })
    if circle == 0:
        parinfo.append({
            'n': 5,
            'value': params[5],
            'limits': [minpars[5], maxpars[5]],
            'limited': [limitedmin[5], limitedmax[5]],
            'fixed': fixed[5],
            'parname': "YWIDTH",
            'error': 0
        })
        if rotate == 1:
            parinfo.append({
                'n': 6,
                'value': params[6],
                'limits': [minpars[6], maxpars[6]],
                'limited': [limitedmin[6], limitedmax[6]],
                'fixed': fixed[6],
                'parname': "ROTATION",
                'error': 0
            })

    if autoderiv == 0:
        # the analytic derivative, while not terribly difficult, is less
        # efficient and useful.  I only bothered putting it here because I was
        # instructed to do so for a class project - please ask if you would
        # like this feature implemented
        raise ValueError("I'm sorry, I haven't implemented this feature yet.")
    else:
        #        p, cov, infodict, errmsg, success = optimize.leastsq(errorfunction,\
        #                params, full_output=1)
        mp = mpfit(mpfitfun(data, err), parinfo=parinfo, quiet=quiet)

    if returnmp:
        returns = (mp)
    elif return_all == 0:
        returns = mp.params
    elif return_all == 1:
        returns = mp.params, mp.perror
    if returnfitimage:
        fitimage = twodgaussian(mp.params, circle, rotate,
                                vheight)(*numpy.indices(data.shape))
        returns = (returns, fitimage)
    return returns
Example #5
0
def multigaussfit(xax, data, ngauss=1, err=None, params=[1,0,1],
        fixed=[False,False,False], limitedmin=[False,False,True],
        limitedmax=[False,False,False], minpars=[0,0,0], maxpars=[0,0,0],
        quiet=True, shh=True, veryverbose=False):
    """
    An improvement on onedgaussfit.  Lets you fit multiple gaussians.

    Inputs:
       xax - x axis
       data - y axis
       ngauss - How many gaussians to fit?  Default 1 (this could supersede onedgaussfit)
       err - error corresponding to data

     These parameters need to have length = 3*ngauss.  If ngauss > 1 and length = 3, they will
     be replicated ngauss times, otherwise they will be reset to defaults:
       params - Fit parameters: [amplitude, offset, width] * ngauss
              If len(params) % 3 == 0, ngauss will be set to len(params) / 3
       fixed - Is parameter fixed?
       limitedmin/minpars - set lower limits on each parameter (default: width>0)
       limitedmax/maxpars - set upper limits on each parameter

       quiet - should MPFIT output each iteration?
       shh - output final parameters?

    Returns:
       Fit parameters
       Model
       Fit errors
       chi2
    """

    if len(params) != ngauss and (len(params) / 3) > ngauss:
        ngauss = len(params) / 3 

    if isinstance(params,np.ndarray): params=params.tolist()

    # make sure all various things are the right length; if they're not, fix them using the defaults
    for parlist in (params,fixed,limitedmin,limitedmax,minpars,maxpars):
        if len(parlist) != 3*ngauss:
            # if you leave the defaults, or enter something that can be multiplied by 3 to get to the
            # right number of gaussians, it will just replicate
            if len(parlist) == 3: 
                parlist *= ngauss 
            elif parlist==params:
                parlist[:] = [1,0,1] * ngauss
            elif parlist==fixed or parlist==limitedmax:
                parlist[:] = [False,False,False] * ngauss
            elif parlist==limitedmin:
                parlist[:] = [False,False,True] * ngauss
            elif parlist==minpars or parlist==maxpars:
                parlist[:] = [0,0,0] * ngauss

    def mpfitfun(x,y,err):
        if err is None:
            def f(p,fjac=None): return [0,(y-n_gaussian(pars=p)(x))]
        else:
            def f(p,fjac=None): return [0,(y-n_gaussian(pars=p)(x))/err]
        return f

    if xax == None:
        xax = np.arange(len(data))

    parnames = {0:"AMPLITUDE",1:"SHIFT",2:"WIDTH"}

    parinfo = [ {'n':ii, 'value':params[ii],
        'limits':[minpars[ii],maxpars[ii]],
        'limited':[limitedmin[ii],limitedmax[ii]], 'fixed':fixed[ii],
        'parname':parnames[ii%3]+str(ii%3), 'error':ii} 
        for ii in xrange(len(params)) ]

    if veryverbose:
        print "GUESSES: "
        print "\n".join(["%s: %s" % (p['parname'],p['value']) for p in parinfo])

    mp = mpfit(mpfitfun(xax,data,err),parinfo=parinfo,quiet=quiet)
    mpp = mp.params
    mpperr = mp.perror
    chi2 = mp.fnorm

    if mp.status == 0:
        raise Exception(mp.errmsg)

    if not shh:
        print "Final fit values: "
        for i,p in enumerate(mpp):
            parinfo[i]['value'] = p
            print parinfo[i]['parname'],p," +/- ",mpperr[i]
        print "Chi2: ",mp.fnorm," Reduced Chi2: ",mp.fnorm/len(data)," DOF:",len(data)-len(mpp)

    return mpp,n_gaussian(pars=mpp)(xax),mpperr,chi2
Example #6
0
def onedgaussfit(xax, data, err=None,
        params=[0,1,0,1],fixed=[False,False,False,False],
        limitedmin=[False,False,False,True],
        limitedmax=[False,False,False,False], minpars=[0,0,0,0],
        maxpars=[0,0,0,0], quiet=True, shh=True,
        veryverbose=False,
        vheight=True, negamp=False,
        usemoments=False):
    """
    Inputs:
       xax - x axis
       data - y axis
       err - error corresponding to data

       params - Fit parameters: Height of background, Amplitude, Shift, Width
       fixed - Is parameter fixed?
       limitedmin/minpars - set lower limits on each parameter (default: width>0)
       limitedmax/maxpars - set upper limits on each parameter
       quiet - should MPFIT output each iteration?
       shh - output final parameters?
       usemoments - replace default parameters with moments

    Returns:
       Fit parameters
       Model
       Fit errors
       chi2
    """

    def mpfitfun(x,y,err):
        if err is None:
            def f(p,fjac=None): return [0,(y-onedgaussian(x,*p))]
        else:
            def f(p,fjac=None): return [0,(y-onedgaussian(x,*p))/err]
        return f

    if xax == None:
        xax = np.arange(len(data))

    if vheight is False: 
        height = params[0]
        fixed[0] = True
    if usemoments:
        params = onedmoments(xax,data,vheight=vheight,negamp=negamp, veryverbose=veryverbose)
        if vheight is False: params = [height]+params
        if veryverbose: print "OneD moments: h: %g  a: %g  c: %g  w: %g" % tuple(params)

    parinfo = [ {'n':0,'value':params[0],'limits':[minpars[0],maxpars[0]],'limited':[limitedmin[0],limitedmax[0]],'fixed':fixed[0],'parname':"HEIGHT",'error':0} ,
                {'n':1,'value':params[1],'limits':[minpars[1],maxpars[1]],'limited':[limitedmin[1],limitedmax[1]],'fixed':fixed[1],'parname':"AMPLITUDE",'error':0},
                {'n':2,'value':params[2],'limits':[minpars[2],maxpars[2]],'limited':[limitedmin[2],limitedmax[2]],'fixed':fixed[2],'parname':"SHIFT",'error':0},
                {'n':3,'value':params[3],'limits':[minpars[3],maxpars[3]],'limited':[limitedmin[3],limitedmax[3]],'fixed':fixed[3],'parname':"WIDTH",'error':0}]

    mp = mpfit(mpfitfun(xax,data,err),parinfo=parinfo,quiet=quiet)
    mpp = mp.params
    mpperr = mp.perror
    chi2 = mp.fnorm

    if mp.status == 0:
        raise Exception(mp.errmsg)

    if (not shh) or veryverbose:
        print "Fit status: ",mp.status
        for i,p in enumerate(mpp):
            parinfo[i]['value'] = p
            print parinfo[i]['parname'],p," +/- ",mpperr[i]
        print "Chi2: ",mp.fnorm," Reduced Chi2: ",mp.fnorm/len(data)," DOF:",len(data)-len(mpp)

    return mpp,onedgaussian(xax,*mpp),mpperr,chi2
Example #7
0
def gaussfit(data,err=None,params=(),autoderiv=True,return_all=False,circle=False,
        fixed=np.repeat(False,7),limitedmin=[False,False,False,False,True,True,True],
        limitedmax=[False,False,False,False,False,False,True],
        usemoment=np.array([],dtype='bool'),
        minpars=np.repeat(0,7),maxpars=[0,0,0,0,0,0,360],
        rotate=1,vheight=1,quiet=True,returnmp=False,
        returnfitimage=False,**kwargs):
    """
    Gaussian fitter with the ability to fit a variety of different forms of
    2-dimensional gaussian.
    
    Input Parameters:
        data - 2-dimensional data array
        err=None - error array with same size as data array
        params=[] - initial input parameters for Gaussian function.
            (height, amplitude, x, y, width_x, width_y, rota)
            if not input, these will be determined from the moments of the system, 
            assuming no rotation
        autoderiv=1 - use the autoderiv provided in the lmder.f function (the
            alternative is to us an analytic derivative with lmdif.f: this method
            is less robust)
        return_all=0 - Default is to return only the Gaussian parameters.  
                   1 - fit params, fit error
        returnfitimage - returns (best fit params,best fit image)
        returnmp - returns the full mpfit struct
        circle=0 - default is an elliptical gaussian (different x, y widths),
            but can reduce the input by one parameter if it's a circular gaussian
        rotate=1 - default allows rotation of the gaussian ellipse.  Can remove
            last parameter by setting rotate=0.  np.expects angle in DEGREES
        vheight=1 - default allows a variable height-above-zero, i.e. an
            additive constant for the Gaussian function.  Can remove first
            parameter by setting this to 0
        usemoment - can choose which parameters to use a moment estimation for.
            Other parameters will be taken from params.  Needs to be a boolean
            array.

    Output:
        Default output is a set of Gaussian parameters with the same shape as
            the input parameters

        If returnfitimage=True returns a np array of a gaussian
            contructed using the best fit parameters.

        If returnmp=True returns a `mpfit` object. This object contains
            a `covar` attribute which is the 7x7 covariance array
            generated by the mpfit class in the `mpfit_custom.py`
            module. It contains a `param` attribute that contains a
            list of the best fit parameters in the same order as the
            optional input parameter `params`.

        Warning: Does NOT necessarily output a rotation angle between 0 and 360 degrees.
    """
    usemoment=np.array(usemoment,dtype='bool')
    params=np.array(params,dtype='float')
    if usemoment.any() and len(params)==len(usemoment):
        moment = np.array(moments(data,circle,rotate,vheight,**kwargs),dtype='float')
        params[usemoment] = moment[usemoment]
    elif params == [] or len(params)==0:
        params = (moments(data,circle,rotate,vheight,**kwargs))
    if vheight==0:
        vheight=1
        params = np.concatenate([[0],params])
        fixed[0] = 1


    # mpfit will fail if it is given a start parameter outside the allowed range:
    for i in xrange(len(params)): 
        if params[i] > maxpars[i] and limitedmax[i]: params[i] = maxpars[i]
        if params[i] < minpars[i] and limitedmin[i]: params[i] = minpars[i]

    if err is None:
        errorfunction = lambda p: np.ravel((twodgaussian(p,circle,rotate,vheight)\
                (*np.indices(data.shape)) - data))
    else:
        errorfunction = lambda p: np.ravel((twodgaussian(p,circle,rotate,vheight)\
                (*np.indices(data.shape)) - data)/err)
    def mpfitfun(data,err):
        if err is None:
            def f(p,fjac=None): return [0,np.ravel(data-twodgaussian(p,circle,rotate,vheight)\
                    (*np.indices(data.shape)))]
        else:
            def f(p,fjac=None): return [0,np.ravel((data-twodgaussian(p,circle,rotate,vheight)\
                    (*np.indices(data.shape)))/err)]
        return f

                    
    parinfo = [ 
                {'n':1,'value':params[1],'limits':[minpars[1],maxpars[1]],'limited':[limitedmin[1],limitedmax[1]],'fixed':fixed[1],'parname':"AMPLITUDE",'error':0},
                {'n':2,'value':params[2],'limits':[minpars[2],maxpars[2]],'limited':[limitedmin[2],limitedmax[2]],'fixed':fixed[2],'parname':"XSHIFT",'error':0},
                {'n':3,'value':params[3],'limits':[minpars[3],maxpars[3]],'limited':[limitedmin[3],limitedmax[3]],'fixed':fixed[3],'parname':"YSHIFT",'error':0},
                {'n':4,'value':params[4],'limits':[minpars[4],maxpars[4]],'limited':[limitedmin[4],limitedmax[4]],'fixed':fixed[4],'parname':"XWIDTH",'error':0} ]
    if vheight == 1:
        parinfo.insert(0,{'n':0,'value':params[0],'limits':[minpars[0],maxpars[0]],'limited':[limitedmin[0],limitedmax[0]],'fixed':fixed[0],'parname':"HEIGHT",'error':0})
    if circle == 0:
        parinfo.append({'n':5,'value':params[5],'limits':[minpars[5],maxpars[5]],'limited':[limitedmin[5],limitedmax[5]],'fixed':fixed[5],'parname':"YWIDTH",'error':0})
        if rotate == 1:
            parinfo.append({'n':6,'value':params[6],'limits':[minpars[6],maxpars[6]],'limited':[limitedmin[6],limitedmax[6]],'fixed':fixed[6],'parname':"ROTATION",'error':0})

    if autoderiv == 0:
        # the analytic derivative, while not terribly difficult, is less
        # efficient and useful.  I only bothered putting it here because I was
        # instructed to do so for a class project - please ask if you would
        # like this feature implemented
        raise ValueError("I'm sorry, I haven't implemented this feature yet.")
    else:
#        p, cov, infodict, errmsg, success = optimize.leastsq(errorfunction,\
#                params, full_output=1)
        mp = mpfit(mpfitfun(data,err),parinfo=parinfo,quiet=quiet)


    if returnmp:
        returns = (mp)
    elif return_all == 0:
        returns = mp.params
    elif return_all == 1:
        returns = mp.params,mp.perror
    if returnfitimage:
        fitimage = twodgaussian(mp.params,circle,rotate,vheight)(*np.indices(data.shape))
        returns = (returns,fitimage)
    return returns
Example #8
0
def onedgaussfit(xax,
                 data,
                 err=None,
                 params=[0, 1, 0, 1],
                 fixed=[False, False, False, False],
                 limitedmin=[False, False, False, True],
                 limitedmax=[False, False, False, False],
                 minpars=[0, 0, 0, 0],
                 maxpars=[0, 0, 0, 0],
                 quiet=True,
                 shh=True,
                 veryverbose=False,
                 vheight=True,
                 negamp=False,
                 usemoments=False):
    """
    Inputs:
       xax - x axis
       data - y axis
       err - error corresponding to data

       params - Fit parameters: Height of background, Amplitude, Shift, Width
       fixed - Is parameter fixed?
       limitedmin/minpars - set lower limits on each parameter (default: width>0)
       limitedmax/maxpars - set upper limits on each parameter
       quiet - should MPFIT output each iteration?
       shh - output final parameters?
       usemoments - replace default parameters with moments

    Returns:
       Fit parameters
       Model
       Fit errors
       chi2
    """
    def mpfitfun(x, y, err):
        if err is None:

            def f(p, fjac=None):
                return [0, (y - onedgaussian(x, *p))]
        else:

            def f(p, fjac=None):
                return [0, (y - onedgaussian(x, *p)) / err]

        return f

    if xax == None:
        xax = np.arange(len(data))

    if vheight is False:
        height = params[0]
        fixed[0] = True
    if usemoments:
        params = onedmoments(xax,
                             data,
                             vheight=vheight,
                             negamp=negamp,
                             veryverbose=veryverbose)
        if vheight is False: params = [height] + params
        if veryverbose:
            print "OneD moments: h: %g  a: %g  c: %g  w: %g" % tuple(params)

    parinfo = [{
        'n': 0,
        'value': params[0],
        'limits': [minpars[0], maxpars[0]],
        'limited': [limitedmin[0], limitedmax[0]],
        'fixed': fixed[0],
        'parname': "HEIGHT",
        'error': 0
    }, {
        'n': 1,
        'value': params[1],
        'limits': [minpars[1], maxpars[1]],
        'limited': [limitedmin[1], limitedmax[1]],
        'fixed': fixed[1],
        'parname': "AMPLITUDE",
        'error': 0
    }, {
        'n': 2,
        'value': params[2],
        'limits': [minpars[2], maxpars[2]],
        'limited': [limitedmin[2], limitedmax[2]],
        'fixed': fixed[2],
        'parname': "SHIFT",
        'error': 0
    }, {
        'n': 3,
        'value': params[3],
        'limits': [minpars[3], maxpars[3]],
        'limited': [limitedmin[3], limitedmax[3]],
        'fixed': fixed[3],
        'parname': "WIDTH",
        'error': 0
    }]

    mp = mpfit(mpfitfun(xax, data, err), parinfo=parinfo, quiet=quiet)
    mpp = mp.params
    mpperr = mp.perror
    chi2 = mp.fnorm

    if mp.status == 0:
        raise Exception(mp.errmsg)

    if (not shh) or veryverbose:
        print "Fit status: ", mp.status
        for i, p in enumerate(mpp):
            parinfo[i]['value'] = p
            print parinfo[i]['parname'], p, " +/- ", mpperr[i]
        print "Chi2: ", mp.fnorm, " Reduced Chi2: ", mp.fnorm / len(
            data), " DOF:", len(data) - len(mpp)

    return mpp, onedgaussian(xax, *mpp), mpperr, chi2
Example #9
0
def call_mpfit(FUNCTION, INIT_PARAM, x, y, error, with_plot = False):
    """
    This method makes fit of function(par,x) to experimental data
    contained in X,Y arrays.
    
    (1)the FUNCTION must be defined as follows:
    
    def func(param,x):
      value = some_formula(param[0],param[1]..., x)
      return value

    (2)INIT_PARAM -- is a list of initial values of parameters
    
    (3) X exp. data
    (4) Y experimental data

    Return: [list of fited parameters], [list of parameters errors],
    Chi2-value
    """
    def mpfitfunc(x,y,err):
        if err == None:
            def f(p,fjac=None): 
                return [0,(y-FUNCTION(p,x))]
        else:
            def f(p,fjac=None): 
                return [0,(y-FUNCTION(p,x))/err]
        return f    
    mpfitparaminfo = generate_mpfit_info(INIT_PARAM)
    mp2 = mpfit(mpfitfunc(x,y,error),
                parinfo=mpfitparaminfo,quiet=0)
    fit_params   = mp2.params
    fit_par_error= mp2.perror
    chi2   = mp2.fnorm
    if len(fit_params)>0:
        print()
        print("MPFIT ALGORITHM RESULT:")
        N_params = len(INIT_PARAM)
        p_cnt=-1
        output_string = ' '
        #for a report about obtained param value into a string:
        for p in fit_params:
            p_cnt+=1
            string = str()
            if fit_par_error!=None:
                string = "PARAM "+str(p_cnt)+":\t"+str(p)+"+/-("+str(fit_par_error[p_cnt])+")\n"
                print(string)
            else:
                string = "PARAM "+str(p_cnt)+":\t"+str(p)+"\n"
                print(string)
            output_string+=string
        #end for
        output_string += 'Chi2: '+str(chi2)
        #write that string to the file:
        param_file = open("params.mpfit.txt", 'w')
        param_file.write(output_string)
        param_file.close()

        #write fited function values at X into output file.
        FUNC_VAL = numpy.zeros(len(x))
        FUNC_VAL = FUNCTION(fit_params, x)
        write_arrays( [x, FUNC_VAL], "output.mpfit.txt")
        print ("Chi2: "+str( chi2))
        if with_plot:
            PLT.plot(x,y,'+', x,FUNC_VAL,'-');
            PLT.legend(['data','formula approx.'],loc='best')
            PLT.show()
        # end if with_plot
    
    if fit_par_error!=None:
        return fit_params,chi2
    else:
        return fit_params, fit_par_error,chi2
    return fit_params
Example #10
0
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def func(x, a, b, c):
  #return a * np.exp(-b * x) + c
  return a * np.log(b * x) + c

x = np.linspace(1,5,50)   # changed boundary conditions to avoid division by 0
y = func(x, 2.5, 1.3, 0.5)
yn = y + 0.2*np.random.normal(size=len(x))

popt, pcov = curve_fit(func, x, yn)

plt.figure()
plt.plot(x, yn, 'ko', label="Original Noised Data")
plt.plot(x, func(x, *popt), 'r-', label="Fitted Curve")
plt.legend()
plt.show()
"""
import mpfit
import Numeric
x = Numeric.arange(100, Numeric.float)
p0 = [5.7, 2.2, 500., 1.5, 2000.]
y = ( p[0] + p[1]*[x] + p[2]*[x**2] + p[3]*Numeric.sqrt(x) +
     p[4]*Numeric.log(x))
fa = {'x':x, 'y':y, 'err':err}
m = mpfit('myfunct', p0, functkw=fa)
print 'status = ', m.status
if (m.status <= 0): print 'error message = ', m.errmsg
print 'parameters = ', m.params