Esempio n. 1
0
def fitGaussian(I=None, p0=None, bounds=None, nGaussians=1, display=False):
    '''
    Takes an nxm matrix and returns an nxm matrix which is the gaussian fit
    of the first.  p0 is a list of parameters [xorigin, yorigin, sigma,amplitude]
    0-19 should be [-.2889 -.3265 -.3679 -.4263 -.5016 -.6006 ... -.0228 .01913]
    '''

    x=np.arange(I.shape[0])
    y=np.arange(I.shape[1])
    if display:
        data=Puff3d(I,'Original Data')
    X=[x,y]
    p0=[round(p,3) for p in p0] 
    if nGaussians==1:
        p, cov_x, infodic, mesg, ier = leastsqbound(err, p0,args=(I,X),bounds = bounds,ftol=.0000001,full_output=True)
        #xorigin,yorigin,sigmax,sigmay,angle,amplitude=p
        I_fit=gaussian(x[:,None], y[None,:],*p)
        if not display:
            return p, I_fit, I_fit
        else:
            fitted_data=Puff3d(I_fit,'Fitted')
            return data, fitted_data, p
    elif nGaussians>=2:
        p, cov_x, infodic, mesg, ier = leastsqbound(err2, p0,args=(I,X),bounds = bounds,ftol=.0000001,full_output=True)
        #xorigin,yorigin,sigmax,sigmay,angle,amplitude=p
        I_fit=gaussian(x[:,None], y[None,:],*(p[:4]))
        I_fit2=gaussian2(x[:,None], y[None,:],*p)
        return p[:4], I_fit, I_fit2
def fitGaussian(I=None, p0=None, bounds=None, nGaussians=1, display=False):
    '''
    Takes an nxm matrix and returns an nxm matrix which is the gaussian fit
    of the first.  p0 is a list of parameters [xorigin, yorigin, sigma,amplitude]
    0-19 should be [-.2889 -.3265 -.3679 -.4263 -.5016 -.6006 ... -.0228 .01913]
    '''

    x=np.arange(I.shape[0])
    y=np.arange(I.shape[1])
    if display:
        data=Puff3d(I,'Original Data')
    X=[x,y]
    p0=[round(p,3) for p in p0] 
    if nGaussians==1:
        p, cov_x, infodic, mesg, ier = leastsqbound(err, p0,args=(I,X),bounds = bounds,ftol=.0000001,full_output=True)
        #xorigin,yorigin,sigmax,sigmay,angle,amplitude=p
        I_fit=gaussian(x[:,None], y[None,:],*p)
        if not display:
            return p, I_fit, I_fit
        else:
            fitted_data=Puff3d(I_fit,'Fitted')
            return data, fitted_data, p
    elif nGaussians>=2:
        p, cov_x, infodic, mesg, ier = leastsqbound(err2, p0,args=(I,X),bounds = bounds,ftol=.0000001,full_output=True)
        #xorigin,yorigin,sigmax,sigmay,angle,amplitude=p
        I_fit=gaussian(x[:,None], y[None,:],*(p[:4]))
        I_fit2=gaussian2(x[:,None], y[None,:],*p)
        return p[:4], I_fit, I_fit2
Esempio n. 3
0
def fitGaussian(I, r, maxSigmaForGaussianFit, rotatedFit):
    # takes an nxm matrix and returns an nxm matrix which is the gaussian fit
    # of the first.  c is a list of parameters [zoffset, scale, xorigin, yorigin, sigma]
    I[I<0]=0
    startx=round(np.mean(r[0:2]))
    starty=round(np.mean(r[2:4]))
    center=I[r[0]:r[1],r[2]:r[3]]
    scale=np.max(center.ravel())
    if scale>0:
        I=np.divide(I,scale)
    n,m=np.shape(I)
    Y,X=np.meshgrid(range(1, m+1),range(1, n+1))
    x = np.zeros((np.size(X), 2))
    x[:, 0] = X.ravel('F')
    x[:, 1] = Y.ravel('F')
    I_col=I.ravel('F')
    if not rotatedFit: # fun = e ^ (-())
        def fun(c, x, minus=True):
            if minus==False:
                return np.exp(-((x[:, 0]-c[0])/c[2])**2-((x[:, 1]-c[1])/c[2])**2)
            return I_col - np.exp(-((x[:, 0]-c[0])/c[2])**2-((x[:, 1]-c[1])/c[2])**2)
    #%     [  xorigin,  yorigin, sigma]
        c0=[startx,starty,m] #starting parameters
        lb=[r[0],r[2],1 ] #lower bounds on the parameters
        ub=[r[1],r[3],maxSigmaForGaussianFit] #upper bounds on the parameters
        for i in range(len(c0)):
            c0[i] = max(lb[i], c0[i])
            c0[i] = min(ub[i], c0[i])
        c = leastsqbound(fun, c0, args=(x,), bounds = zip(lb, ub), ftol = 1.0e-4, maxfev=100)

    else: #if we are fitting to a 2d rotating gaussian fit
        def fun(c, x, minus=True):
            if not minus:
                return np.exp(-(((x[:, 0] - c[0])*cosd(c[4])+(x[:, 1] - c[1])*sind(c[4]))/c[2])**2 - (((x[:, 0] - c[0])*sind(c[4])+(x[:, 1] - c[1])*cosd(c[4]))/c[3])**2)
            return I_col - np.exp(-(((x[:, 0] - c[0])*cosd(c[4])+(x[:, 1] - c[1])*sind(c[4]))/c[2])**2 - (((x[:, 0] - c[0])*sind(c[4])+(x[:, 1] - c[1])*cosd(c[4]))/c[3])**2)
    #%     [xorigin yorigin sigmax sigmay angle]
        c0=[startx, starty, m, m, 90] #starting parameters
        lb=[r[0], r[2], 1, 1, 0] #lower bounds on the parameters
        ub=[r[1], r[3], maxSigmaForGaussianFit, maxSigmaForGaussianFit, 180] #upper bounds on the parameters
        for i in range(len(c0)):
            c0[i] = max(lb[i], c0[i])
            c0[i] = min(ub[i], c0[i])
        c = leastsqbound(fun, c0, args=(x,), bounds = zip(lb, ub), ftol = 1.0e-6, maxfev=100)
    c = c[0]
    Ifit=fun(c, np.double(x), minus=False)
    Ifit=np.reshape(Ifit,(n, m), 'F')
    graph_args = [I, Ifit, X, Y]

    return c, graph_args
Esempio n. 4
0
def run_leastsq_bound(problem, ftol, xtol, gtol, jac,
                      scaling=None, **kwargs):
    bounds, lb, ub = scipy_bounds(problem)

    if scaling is None:
        diag = np.ones_like(problem.x0)
    else:
        diag = None

    if jac in ['2-point', '3-point']:
        jac = None
    else:
        jac = problem.jac

    x, cov_x, info, mesg, ier = leastsqbound(
        problem.fun, problem.x0, bounds=bounds, full_output=True,
        Dfun=jac, ftol=ftol, xtol=xtol, gtol=gtol, diag=diag, **kwargs)

    x = make_strictly_feasible(x, lb, ub)
    f = problem.fun(x)
    g = problem.grad(x)
    optimality = CL_optimality(x, g, lb, ub)
    active = find_active_constraints(x, lb, ub)
    return (info['nfev'], optimality, 0.5 * np.dot(f, f),
            np.sum(active != 0), ier)
Esempio n. 5
0
File: fit.py Progetto: Eljee/symfit
    def execute(self, *args, **kwargs):
        """
        Run fitting and initiate a fit report with the result.
        :return: FitResults object
        """
        popt, cov_x, infodic, mesg, ier = leastsqbound(
            self.error,
            self.get_initial_guesses(),
            args=(self.scipy_func, self.xdata, self.ydata),
            bounds=self.get_bounds(),
            Dfun=self.get_jacobian,
            full_output=True,
            *args,
            **kwargs
        )

        s_sq = (infodic['fvec']**2).sum()/(len(self.ydata)-len(popt))
        # For fixed parameters, there is no stdev.
        pcov =  cov_x*s_sq
        self.fit_results = FitResults(
            params=self.params,
            popt=popt,
            pcov=pcov,
            infodic=infodic,
            mesg=mesg,
            ier=ier,
            ydata=self.ydata,  # Needed to calculate R^2
        )
        return self.fit_results
Esempio n. 6
0
def run_leastsq_bound(problem, ftol, xtol, gtol, jac, scaling=None, **kwargs):
    bounds, lb, ub = scipy_bounds(problem)

    if scaling is None:
        diag = np.ones_like(problem.x0)
    else:
        diag = None

    if jac in ['2-point', '3-point']:
        jac = None
    else:
        jac = problem.jac

    x, cov_x, info, mesg, ier = leastsqbound(problem.fun,
                                             problem.x0,
                                             bounds=bounds,
                                             full_output=True,
                                             Dfun=jac,
                                             ftol=ftol,
                                             xtol=xtol,
                                             gtol=gtol,
                                             diag=diag,
                                             **kwargs)

    x = make_strictly_feasible(x, lb, ub)
    f = problem.fun(x)
    g = problem.grad(x)
    optimality = CL_optimality(x, g, lb, ub)
    active = find_active_constraints(x, lb, ub)
    return (info['nfev'], optimality, 0.5 * np.dot(f, f), np.sum(active != 0),
            ier)
def fit_exponential(x,y,order=1):
    p0=(1,.0005)*order
    popt, cov_x, infodic, mesg, ier = leastsqbound(err, p0, args=(y,x), full_output=True)
    if order==1:
        yfit=exp_decay_1st_order(x, *popt)
    elif order==2:
        yfit=exp_decay_2nd_order(x, *popt)
    elif order==3:
        yfit=exp_decay_3rd_order(x, *popt)
    return popt,yfit
Esempio n. 8
0
def fit_curve(f, xdata, ydata, guess, bounds):
    """Fit a curve to data."""
    def residual(p, x, y):
        return f(p, x) - y

    params, ier = leastsqbound(residual, guess, args=(xdata, ydata),
                               bounds=bounds)
    if 0 < ier < 5:
        err = rmse(f, params, xdata, ydata)
    else:
        err = np.inf
    return params, err
Esempio n. 9
0
def fit_exponential(x, y, order=1):
    p0 = (1, .0005) * order
    popt, cov_x, infodic, mesg, ier = leastsqbound(err,
                                                   p0,
                                                   args=(y, x),
                                                   full_output=True)
    if order == 1:
        yfit = exp_decay_1st_order(x, *popt)
    elif order == 2:
        yfit = exp_decay_2nd_order(x, *popt)
    elif order == 3:
        yfit = exp_decay_3rd_order(x, *popt)
    return popt, yfit
Esempio n. 10
0
def fit_curve(f, xdata, ydata, guess, bounds):
    """Fit a curve to data."""
    def residual(p, x, y):
        return f(p, x) - y

    params, ier = leastsqbound(residual,
                               guess,
                               args=(xdata, ydata),
                               bounds=bounds)
    if 0 < ier < 5:
        err = rmse(f, params, xdata, ydata)
    else:
        err = np.inf
    return params, err
def fitGaussian(I=None, p0=None, bounds=None):
    '''
    Takes an nxm matrix and returns an nxm matrix which is the gaussian fit
    of the first.  p0 is a list of parameters [xorigin, yorigin, sigma,amplitude]
    '''

    x=np.arange(I.shape[0])
    y=np.arange(I.shape[1])
    X=[x,y]
    p0=[round(p,3) for p in p0] 
    p, cov_x, infodic, mesg, ier = leastsqbound(err, p0,args=(I,X),bounds = bounds,ftol=.0000001,full_output=True)
    #xorigin,yorigin,sigmax,sigmay,angle,amplitude=p
    I_fit=gaussian(x[:,None], y[None,:],*p)
    return p, I_fit, I_fit
Esempio n. 12
0
def fitGaussian(I=None, p0=None, bounds=None):
    '''
    Takes an nxm matrix and returns an nxm matrix which is the gaussian fit
    of the first.  p0 is a list of parameters [xorigin, yorigin, sigma,amplitude]
    '''

    x = np.arange(I.shape[0])
    y = np.arange(I.shape[1])
    X = [x, y]
    p0 = [round(p, 3) for p in p0]
    p, cov_x, infodic, mesg, ier = leastsqbound(err,
                                                p0,
                                                args=(I, X),
                                                bounds=bounds,
                                                ftol=.0000001,
                                                full_output=True)
    #xorigin,yorigin,sigmax,sigmay,angle,amplitude=p
    I_fit = gaussian(x[:, None], y[None, :], *p)
    return p, I_fit, I_fit
def leastsq_oracle(x, y, kernel, initial=None, bounds=None):
    """
    This is a generic oracle function that uses bounded least squares to find
    the parameters in each iteration of EBP, and requires initial parameters. 

    Parameters
    ----------
    x : ndarray
        Input to the kernel function.
    y : ndarray
        Data to fit to.
    kernel : callalble
       The kernel function to be specified by this oracle.
    initial : list/array
        initial setting for the parameters of the function. This has to be
        something that kernel knows what to do with.
    """
    return lsq.leastsqbound(err_func, initial, args=(x, y, kernel),
                            bounds=bounds)[0]
def Fit_ExpDecFunction(x, y, bounders, guess):
    ##########
    # Fitting the data -- Least Squares Method
    ##########
    # Exp Decay fitting
    import scipy, numpy as np, leastsqbound
    fitfunc = lambda p, x: p[0]*np.exp(-p[1]*x) + p[2]#target fun. notice this is a linear fun. 
    errfunc = lambda p, x, y: (y - fitfunc(p, x)) #distance from our target fun
    pinit = guess #inital parameter guess
    pfinal,covar,infodict,mesg,ier = leastsqbound.leastsqbound(errfunc, pinit, args=(x, y), bounds=bounders,full_output=1)    
    index = pfinal[1]
    amp = pfinal[0]
    asmp = pfinal[2]
    ss_err = (infodict['fvec']**2).sum()
    ss_tot = ((y-y.mean())**2).sum()
    rsquared = 1-(ss_err/ss_tot)
    dof = len(x)-len(pfinal)
    rmse = np.sqrt(ss_err/dof)
    return (rmse, index, amp, asmp, rsquared)
Esempio n. 15
0
def f_NDregion(region,ls_classes,p0,p_bounds,n_peaks,wmask,**kw):
    """
    Fit an arbitrary dimensional regions  containing one or more peaks 
    using a contrained Levenberg-Marquard optmization algorithm.

    Parameters:

    * region        N-dimensional region to fit
    * ls_classes    List of lineshape classes
    * p0            Initial parameter guesses
    * p_bounds      (min,max) pairs for each element of p0
    * n_peaks       Number of peaks
    
    Additional keyword are passed directly to leastsqbound and in turn
    passed to scipy.optimize.leastsq after variable transformation.

    """
    args = (region,region.shape,ls_classes,n_peaks,wmask)
    p_best = leastsqbound(err_NDregion,p0,bounds=p_bounds,args=args,**kw)
    return p_best
Esempio n. 16
0
def fitGaussian(I=None, p0=None, bounds=None):
    """
    SYMETRICAL GAUSSIAN
    Takes an nxm matrix and returns an nxm matrix which is the gaussian fit
    of the first.  p0 is a list of parameters [xorigin, yorigin, sigma,amplitude]
    0-19 should be [-.2889 -.3265 -.3679 -.4263 -.5016 -.6006 ... -.0228 .01913]
    """

    x = np.arange(I.shape[0])
    y = np.arange(I.shape[1])
    X = [x, y]
    p0 = [round(p, 3) for p in p0]
    p, cov_x, infodic, mesg, ier = leastsqbound(err,
                                                p0,
                                                args=(I, X),
                                                bounds=bounds,
                                                maxfev=100,
                                                full_output=True)
    #  xorigin, yorigin, sigma, amplitude=p
    I_fit = gaussian(x[:, None], y[None, :], *p)
    return p, I_fit, I_fit
Esempio n. 17
0
def leastsqboundWrapper(func, x0, args=(), bounds=None, Dfun=None, full_output=0, col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8, gtol=0.0, maxfev=0, epsfcn=0.0, factor=100, diag=None):
    '''Sometimes leastsqbound has a problem where if the input parameters have too many decimals, it won't change at all from the initial guess.  
    This is a hack around that by checking if the first two parameters have changed.  If they haven't, narrow the bounds by half and try again.
    '''
    x0=[round(x,3) for x in x0] 
    p, cov_x, infodic, mesg, ier = leastsqbound(func, x0, args, bounds, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    if p[0]==x0[0]:
        idx=0
    if p[1]==x0[1]:
        idx=1
    else:
        return p
    spread=bounds[idx][1]-bounds[idx][0]
    spread=spread/4
    if spread<.1 or p[-1]<.1:
        print('Origin did not shift during Gaussian Fitting')
        return p
    bounds=bounds[:] #this is required or else you permanently change the bounds
    bounds[idx]=(bounds[idx][0]+spread,bounds[idx][1]-spread)
    p=leastsqboundWrapper(func, x0, args, bounds, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    return p
Esempio n. 18
0
def leastsqboundWrapper(func, x0, args=(), bounds=None, Dfun=None, full_output=0, col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8, gtol=0.0, maxfev=0, epsfcn=0.0, factor=100, diag=None):
    '''Sometimes leastsqbound has a problem where if the input parameters have too many decimals, it won't change at all from the initial guess.  
    This is a hack around that by checking if the first two parameters have changed.  If they haven't, narrow the bounds by half and try again.
    '''
    x0=[round(x,3) for x in x0] 
    p, cov_x, infodic, mesg, ier = leastsqbound(func, x0, args, bounds, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    if p[0]==x0[0]:
        idx=0
    if p[1]==x0[1]:
        idx=1
    else:
        return p
    spread=bounds[idx][1]-bounds[idx][0]
    spread=spread/4
    if spread<.1 or p[-1]<.1:
        print('Origin did not shift during Gaussian Fitting')
        return p
    bounds=bounds[:] #this is required or else you permanently change the bounds
    bounds[idx]=(bounds[idx][0]+spread,bounds[idx][1]-spread)
    p=leastsqboundWrapper(func, x0, args, bounds, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    return p
Esempio n. 19
0
# print out results
print "Standard Least Squares fitting results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier
print ""

# same as above using no bounds
p0 = [1.0, 0.0]
p, cov_x, infodic, mesg, ier = leastsqbound(err, p0, args=(y, x),
                                            full_output=True)

# print out results
print "Bounded Least Squares fitting with no bounds results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier
print ""

Esempio n. 20
0
def getLine(image,angle=None):
    """
    This function takes a boolean image of a rodent, performs several steps, and returns a line running down the middle of the rodent from nose to tail.
    The steps are:
    1) Find the point at the center of mass.
    2) Draw a horizontal line through this point.
    3) Find the mean distance from the line to every point in the rodent. Rotate the line and find the angle which gives the minimum such distance. Keep the line at this angle. This line gives a good approximation for position.
    4) Draw 7 points on the line: one at the midpoint, two at the ends, two 3/4 away from the midpoint, and two halfway between the ends and the midpoint.
    5) Construct 7 lines which run through the 7 points at an angle perpendicular to the main line.
    6) Draw 6 boxes between these 7 lines.  Find the center of mass for each box along the axes parallel to these lines.  Move each of the 7 points (except the midpoint) along their lines to the center of mass of their respective region.
    7) Draw a box around the end segment of the line.  The bounds for the box lie parallel and perpendicular to this segment.  Fixing the inner point and allowing the end point to vary, fit the segment so that the average distance from the segment to the points in the box are a minimum. This step is done for both ends of the line, because we don't as yet know which end is the head and which is the tail.
    
    """
    pts=np.where(image)
    pts_array=np.column_stack((pts[0],pts[1]))
    pts=MultiPoint([(pts[0][i],pts[1][i]) for i in np.arange(len(pts[0]))])
    # STEP 1
    x0,y0=center_of_mass(image)
    center=Point(x0,y0)
    bounds=pts.bounds
    b_len=((bounds[2]-bounds[0])**2+(bounds[3]-bounds[1])**2)**(1/2) #this is the length of the diagonal, the maximum possible length of an object inside a box
    # STEP 2
    line=pts2line([translate(center,b_len),translate(center,-b_len)])
    # STEP 3
    if angle is None:
        angles=np.arange(-90,90,10)
    else:
        angles=np.arange(angle-20,angle+20,10) #this assumes the angle changes at most 10 degrees between frames
    distances=np.zeros(angles.shape,dtype=np.float)
    for i in np.arange(len(angles)):
        distances[i]=getMeanDistance(rotate(line,angles[i]),pts)
    angle=angles[np.argmin(distances)]
    line=rotate(line,angle)
    line=crop_line(line,pts_array)
    
    # STEP 4 & 5
    # now that we have the approximate line down the main axis, let's divide it in half and allow the endpoints and midpoint to be translated along the perpendicular axis
    start,end=list(line.coords)
    start=np.array(start); end=np.array(end)
    mid=(start+end)/2
    mid_axis=rotate(line,90)
    mid_axis=crop_line(mid_axis,pts_array)
    axis1=translate(mid_axis,xoff=start[0]-mid[0],yoff=start[1]-mid[1])
    axis2=translate(mid_axis,xoff=(start[0]-mid[0])/(4./3),yoff=(start[1]-mid[1])/(4./3.))
    axis3=translate(mid_axis,xoff=(start[0]-mid[0])/2,yoff=(start[1]-mid[1])/2.)
    axis4=translate(mid_axis,xoff=(end[0]-mid[0])/2,yoff=(end[1]-mid[1])/2)
    axis5=translate(mid_axis,xoff=(end[0]-mid[0])/(4./3.),yoff=(end[1]-mid[1])/(4./3.))
    axis6=translate(mid_axis,xoff=end[0]-mid[0],yoff=end[1]-mid[1])
    
    # STEP 6
    pt1=getMeanPoint(axis1,axis2,pts_array)
    pt2=getMeanPoint(axis2,axis3,pts_array)
    pt3=getMeanPoint(axis3,mid_axis,pts_array)
    pt4=getMeanPoint(axis4,mid_axis,pts_array)
    pt5=getMeanPoint(axis5,axis4,pts_array)
    pt6=getMeanPoint(axis6,axis5,pts_array)
    
    # STEP 7
    start=pt1.coords[0]
    end=pt2.coords[0]
    headLine=LineString([start,end])
    headLine=scale(headLine,2,2)
    start=np.array(start); end=np.array(end)
    mid=(start+end)/2
    mid_axis=rotate(headLine,90)
    axis1=translate(mid_axis,xoff=(start[0]-mid[0])*2,yoff=(start[1]-mid[1])*2)
    axis2=translate(mid_axis,xoff=end[0]-mid[0],yoff=end[1]-mid[1])
    #poly=Polygon([p for p in axis1.coords]+[p for p in reversed(axis2.coords)]) #draws a box around one half of the mouse
    #pts_inside=MultiPoint([pt for pt in pts if poly.contains(pt)])
    poly=np.array([p for p in axis1.coords]+[p for p in reversed(axis2.coords)])
    rr, cc = polygon(poly[:, 0], poly[:, 1])
    box_array=np.column_stack((rr,cc))
    pts_inside=multidim_intersect(pts_array,box_array)
    if len(pts_inside)==0: #this only happens when the object lies completely outside of the box at the end of the line
        pts_inside=pts_array 
    pts_inside=MultiPoint([tuple(p) for p in pts_inside])
    
    coor=np.array([np.array(s) for s in axis1.coords])
    pt=end
    p0=(.5,)
    bounds=[(0.0,1.0)]
    p, cov_x, infodic, mesg, ier = leastsqbound(err, p0,args=(coor,pts_inside,pt),bounds = bounds,ftol=.1, full_output=True)     
    headLine=LineString([coor[0]+p[0]*(coor[1]-coor[0]),pt])
    headLine=crop_line(headLine,np.array([np.array([p.x,p.y]) for p in pts_inside]))
    pt1=Point(headLine.coords[1])
    
    start=pt6.coords[0]
    end=pt5.coords[0]
    headLine=LineString([start,end])
    headLine=scale(headLine,2,2)
    start=np.array(start); end=np.array(end)
    mid=(start+end)/2
    mid_axis=rotate(headLine,90)
    axis1=translate(mid_axis,xoff=(start[0]-mid[0])*2,yoff=(start[1]-mid[1])*2)
    axis2=translate(mid_axis,xoff=end[0]-mid[0],yoff=end[1]-mid[1])
    
    #poly=Polygon([p for p in axis1.coords]+[p for p in reversed(axis2.coords)]) #draws a box around one half of the mouse
    #pts_inside=MultiPoint([pt for pt in pts if poly.contains(pt)])
    
    poly=np.array([p for p in axis1.coords]+[p for p in reversed(axis2.coords)])
    rr, cc = polygon(poly[:, 0], poly[:, 1])
    box_array=np.column_stack((rr,cc))
    pts_inside=multidim_intersect(pts_array,box_array)
    if len(pts_inside)==0: #this only happens when the object lies completely outside of the box at the end of the line
        pts_inside=pts_array 
    pts_inside=MultiPoint([tuple(p) for p in pts_inside])
    
    
    
    coor=np.array([np.array(s) for s in axis1.coords])
    pt=end
    p0=(.5,)
    bounds=[(0.0,1.0)]
    p, cov_x, infodic, mesg, ier = leastsqbound(err, p0,args=(coor,pts_inside,pt),bounds = bounds,ftol=.1, full_output=True)     
    headLine=LineString([coor[0]+p[0]*(coor[1]-coor[0]),pt])
    headLine=crop_line(headLine,np.array([np.array([p.x,p.y]) for p in pts_inside]))
    pt6=Point(headLine.coords[1])
    
    line=pts2line([pt1,pt2,pt3,pt4,pt5,pt6])
    return line, angle, center
Esempio n. 21
0
    def leastsq(self, x, y, parameters=None, sigma=None):
        logger = logging.getLogger(__name__)
        # Ensure all values of sigma or non zero by replacing with the minimum nonzero value
        if sigma is not None and self.useErrorBars:
            nonzerosigma = sigma[sigma>0]
            sigma[sigma==0] = numpy.min(nonzerosigma) if len(nonzerosigma)>0 else 1.0
        else:
            sigma = None 
        if parameters is None:
            parameters = [float(param) for param in self.startParameters]
        if self.useSmartStartValues:
            smartParameters = self.smartStartValues(x, y, parameters, self.parameterEnabled)
            if smartParameters is not None:
                parameters = [ smartparam if enabled else param for enabled, param, smartparam in zip(self.parameterEnabled, parameters, smartParameters)]
        
        myEnabledBounds = self.enabledBounds()
        if myEnabledBounds:
            enabledOnlyParameters, cov_x, infodict, self.mesg, self.ier = leastsqbound(self.residuals, self.enabledStartParameters(parameters, bounded=True),
                                                                                                 args=(y, x, sigma), epsfcn=self.epsfcn, full_output=True, bounds=myEnabledBounds)
        else:
            enabledOnlyParameters, cov_x, infodict, self.mesg, self.ier = leastsq(self.residuals, self.enabledStartParameters(parameters), args=(y, x, sigma),
                                                                                            epsfcn=self.epsfcn, full_output=True)
        self.setEnabledFitParameters(enabledOnlyParameters)
        self.update(self.parameters)
        logger.info( "chisq {0}".format( sum(infodict["fvec"]*infodict["fvec"]) ) )        
        
        # calculate final chi square
        self.chisq=sum(infodict["fvec"]*infodict["fvec"])
        
        self.dof = max( len(x)-len(parameters), 1)
        RMSres = Q(sqrt(self.chisq/self.dof))
        RMSres.significantDigits = 3
        self.results['RMSres'].value = RMSres
        # chisq, sqrt(chisq/dof) agrees with gnuplot
        logger.info(  "success {0} {1}".format( self.ier, self.mesg ) )
        logger.info(  "Converged with chi squared {0}".format(self.chisq) )
        logger.info(  "degrees of freedom, dof {0}".format( self.dof ) )
        logger.info(  "RMS of residuals (i.e. sqrt(chisq/dof)) {0}".format( RMSres ) )
        logger.info(  "Reduced chisq (i.e. variance of residuals) {0}".format( self.chisq/self.dof ) )
        
        # uncertainties are calculated as per gnuplot, "fixing" the result
        # for non unit values of the reduced chisq.
        # values at min match gnuplot
        enabledParameterNames = self.enabledParameterNames()
        if cov_x is not None:
            enabledOnlyParametersConfidence = numpy.sqrt(numpy.diagonal(cov_x))*sqrt(self.chisq/self.dof)
            self.setEnabledConfidenceParameters(enabledOnlyParametersConfidence)
            logger.info(  "Fitted parameters at minimum, with 68% C.I.:" )
            for i, pmin in enumerate(enabledOnlyParameters):
                logger.info(  "%2i %-10s %12f +/- %10f"%(i, enabledParameterNames[i], pmin, sqrt(max(cov_x[i, i], 0))*sqrt(self.chisq/self.dof)) )
        
            logger.info(  "Correlation matrix" )
            # correlation matrix close to gnuplot
            messagelist = ["               "]
            for i in range(len(enabledOnlyParameters)): messagelist.append( "%-10s"%(enabledParameterNames[i],) )
            logger.info( " ".join(messagelist))
            messagelist = []
            for i in range(len(enabledOnlyParameters)):
                messagelist.append( "%10s"%enabledParameterNames[i] )
                for j in range(i+1):
                    messagelist.append(  "%10f"%(cov_x[i, j]/sqrt(abs(cov_x[i, i]*cov_x[j, j])),) )
                logger.info( " ".join(messagelist))
    
                #-----------------------------------------------
        else:
            self.parametersConfidence = [None]*len(self.parametersConfidence)
 
        return self.parameters
Esempio n. 22
0
def getLine(image, angle=None):
    """
    This function takes a boolean image of a rodent, performs several steps, and returns a line running down the middle of the rodent from nose to tail.
    The steps are:
    1) Find the point at the center of mass.
    2) Draw a horizontal line through this point.
    3) Find the mean distance from the line to every point in the rodent. Rotate the line and find the angle which gives the minimum such distance. Keep the line at this angle. This line gives a good approximation for position.
    4) Draw 7 points on the line: one at the midpoint, two at the ends, two 3/4 away from the midpoint, and two halfway between the ends and the midpoint.
    5) Construct 7 lines which run through the 7 points at an angle perpendicular to the main line.
    6) Draw 6 boxes between these 7 lines.  Find the center of mass for each box along the axes parallel to these lines.  Move each of the 7 points (except the midpoint) along their lines to the center of mass of their respective region.
    7) Draw a box around the end segment of the line.  The bounds for the box lie parallel and perpendicular to this segment.  Fixing the inner point and allowing the end point to vary, fit the segment so that the average distance from the segment to the points in the box are a minimum. This step is done for both ends of the line, because we don't as yet know which end is the head and which is the tail.
    
    """
    pts = np.where(image)
    pts_array = np.column_stack((pts[0], pts[1]))
    pts = MultiPoint([(pts[0][i], pts[1][i]) for i in np.arange(len(pts[0]))])
    # STEP 1
    x0, y0 = center_of_mass(image)
    center = Point(x0, y0)
    bounds = pts.bounds
    b_len = ((bounds[2] - bounds[0])**2 + (bounds[3] - bounds[1])**2)**(
        1 / 2
    )  #this is the length of the diagonal, the maximum possible length of an object inside a box
    # STEP 2
    line = pts2line([translate(center, b_len), translate(center, -b_len)])
    # STEP 3
    if angle is None:
        angles = np.arange(-90, 90, 10)
    else:
        angles = np.arange(
            angle - 20, angle + 20, 10
        )  #this assumes the angle changes at most 10 degrees between frames
    distances = np.zeros(angles.shape, dtype=np.float)
    for i in np.arange(len(angles)):
        distances[i] = getMeanDistance(rotate(line, angles[i]), pts)
    angle = angles[np.argmin(distances)]
    line = rotate(line, angle)
    line = crop_line(line, pts_array)

    # STEP 4 & 5
    # now that we have the approximate line down the main axis, let's divide it in half and allow the endpoints and midpoint to be translated along the perpendicular axis
    start, end = list(line.coords)
    start = np.array(start)
    end = np.array(end)
    mid = (start + end) / 2
    mid_axis = rotate(line, 90)
    mid_axis = crop_line(mid_axis, pts_array)
    axis1 = translate(mid_axis, xoff=start[0] - mid[0], yoff=start[1] - mid[1])
    axis2 = translate(mid_axis,
                      xoff=(start[0] - mid[0]) / (4. / 3),
                      yoff=(start[1] - mid[1]) / (4. / 3.))
    axis3 = translate(mid_axis,
                      xoff=(start[0] - mid[0]) / 2,
                      yoff=(start[1] - mid[1]) / 2.)
    axis4 = translate(mid_axis,
                      xoff=(end[0] - mid[0]) / 2,
                      yoff=(end[1] - mid[1]) / 2)
    axis5 = translate(mid_axis,
                      xoff=(end[0] - mid[0]) / (4. / 3.),
                      yoff=(end[1] - mid[1]) / (4. / 3.))
    axis6 = translate(mid_axis, xoff=end[0] - mid[0], yoff=end[1] - mid[1])

    # STEP 6
    pt1 = getMeanPoint(axis1, axis2, pts_array)
    pt2 = getMeanPoint(axis2, axis3, pts_array)
    pt3 = getMeanPoint(axis3, mid_axis, pts_array)
    pt4 = getMeanPoint(axis4, mid_axis, pts_array)
    pt5 = getMeanPoint(axis5, axis4, pts_array)
    pt6 = getMeanPoint(axis6, axis5, pts_array)

    # STEP 7
    start = pt1.coords[0]
    end = pt2.coords[0]
    headLine = LineString([start, end])
    headLine = scale(headLine, 2, 2)
    start = np.array(start)
    end = np.array(end)
    mid = (start + end) / 2
    mid_axis = rotate(headLine, 90)
    axis1 = translate(mid_axis,
                      xoff=(start[0] - mid[0]) * 2,
                      yoff=(start[1] - mid[1]) * 2)
    axis2 = translate(mid_axis, xoff=end[0] - mid[0], yoff=end[1] - mid[1])
    #poly=Polygon([p for p in axis1.coords]+[p for p in reversed(axis2.coords)]) #draws a box around one half of the mouse
    #pts_inside=MultiPoint([pt for pt in pts if poly.contains(pt)])
    poly = np.array([p for p in axis1.coords] +
                    [p for p in reversed(axis2.coords)])
    rr, cc = polygon(poly[:, 0], poly[:, 1])
    box_array = np.column_stack((rr, cc))
    pts_inside = multidim_intersect(pts_array, box_array)
    if len(
            pts_inside
    ) == 0:  #this only happens when the object lies completely outside of the box at the end of the line
        pts_inside = pts_array
    pts_inside = MultiPoint([tuple(p) for p in pts_inside])

    coor = np.array([np.array(s) for s in axis1.coords])
    pt = end
    p0 = (.5, )
    bounds = [(0.0, 1.0)]
    p, cov_x, infodic, mesg, ier = leastsqbound(err,
                                                p0,
                                                args=(coor, pts_inside, pt),
                                                bounds=bounds,
                                                ftol=.1,
                                                full_output=True)
    headLine = LineString([coor[0] + p[0] * (coor[1] - coor[0]), pt])
    headLine = crop_line(headLine,
                         np.array([np.array([p.x, p.y]) for p in pts_inside]))
    pt1 = Point(headLine.coords[1])

    start = pt6.coords[0]
    end = pt5.coords[0]
    headLine = LineString([start, end])
    headLine = scale(headLine, 2, 2)
    start = np.array(start)
    end = np.array(end)
    mid = (start + end) / 2
    mid_axis = rotate(headLine, 90)
    axis1 = translate(mid_axis,
                      xoff=(start[0] - mid[0]) * 2,
                      yoff=(start[1] - mid[1]) * 2)
    axis2 = translate(mid_axis, xoff=end[0] - mid[0], yoff=end[1] - mid[1])

    #poly = Polygon([p for p in axis1.coords]+[p for p in reversed(axis2.coords)]) #draws a box around one half of the mouse
    #pts_inside = MultiPoint([pt for pt in pts if poly.contains(pt)])

    poly = np.array([p for p in axis1.coords] +
                    [p for p in reversed(axis2.coords)])
    rr, cc = polygon(poly[:, 0], poly[:, 1])
    box_array = np.column_stack((rr, cc))
    pts_inside = multidim_intersect(pts_array, box_array)
    if len(
            pts_inside
    ) == 0:  #this only happens when the object lies completely outside of the box at the end of the line
        pts_inside = pts_array
    pts_inside = MultiPoint([tuple(p) for p in pts_inside])

    coor = np.array([np.array(s) for s in axis1.coords])
    pt = end
    p0 = (.5, )
    bounds = [(0.0, 1.0)]
    p, cov_x, infodic, mesg, ier = leastsqbound(err,
                                                p0,
                                                args=(coor, pts_inside, pt),
                                                bounds=bounds,
                                                ftol=.1,
                                                full_output=True)
    headLine = LineString([coor[0] + p[0] * (coor[1] - coor[0]), pt])
    headLine = crop_line(headLine,
                         np.array([np.array([p.x, p.y]) for p in pts_inside]))
    pt6 = Point(headLine.coords[1])

    line = pts2line([pt1, pt2, pt3, pt4, pt5, pt6])
    return line, angle, center
Esempio n. 23
0
def leastsqFit(func, x, params, y, err=None, fitOnly=None,
               verbose=False, doNotFit=[], epsfcn=1e-7,
               ftol=1e-4, fullOuput=True,bounds={}):
    """
    - params is a Dict containing the first guess.
    
    - bounds = {"theta":[-0.1,3.24]} even if after it will be a list with same indexation as fitOnly 

    - fits 'y +- err = func(x,params)'. errors are optionnal.

    - fitOnly is a LIST of keywords to fit. By default, it fits all
      parameters in 'params'. Alternatively, one can give a list of
      parameters not to be fitted, as 'doNotFit='

    - doNotFit has a similar purpose: for example if params={'a0':,
      'a1': 'b1':, 'b2':}, doNotFit=['a'] will result in fitting only
    the 'b1' and 'b2'. WARNING: if you name parameter 'A' and another one 'AA',
    you cannot use doNotFit to exclude only 'A' since 'AA' will be excluded as
    well... 
    
    returns bestparam, uncertainties, chi2_reduced, func(x, bestparam)
    """
    # fit all parameters by default
    if fitOnly is None:
        if len(doNotFit)>0:
            fitOnly = filter(lambda x: x not in doNotFit, params.keys())
        else:
            fitOnly = params.keys()

    # build fitted parameters vector:
    pfit = [params[k] for k in fitOnly]

    # built fixed parameters dict:
    pfix = {}
    for k in params.keys():
        if k not in fitOnly:
            pfix[k]=params[k]

    if verbose:
        print '[dpfit] FITTED parameters:', fitOnly
    
    # NO BOUNDS  
    if bounds == {} : 
      # actual fit
      plsq, cov, info, mesg, ier = \
              scipy.optimize.leastsq(fitFunc, pfit,
                    args=(fitOnly,x,y,err,func,pfix, verbose),
                    full_output=True, epsfcn=epsfcn, ftol=ftol)

    # WITH BOUNDS 
    else : #including bounds != {}
       bounds_to_fit=[[None,None]]*len(fitOnly) # now it is a list 
       for key in bounds.keys() :
	    if key in fitOnly : # becauser could be in notToFit
               bounds_to_fit[fitOnly.index(key)] = bounds[key]

       plsq, cov, info, mesg, ier = \
                       leastsqbound(fitFunc, pfit, bounds=bounds_to_fit,
                       args=(fitOnly,x,y,err,func,pfix, verbose),
                       full_output=True, epsfcn=epsfcn, ftol=ftol)
      
    
    # best fit -> agregate to pfix
    for i,k in enumerate(fitOnly):
        pfix[k] = plsq[i]

    # reduced chi2
    model = func(x,pfix)
    chi2 = (np.array(fitFunc(plsq, fitOnly, x, y, err, func, pfix))**2).sum()
    reducedChi2 = chi2/float(reduce(lambda x,y: x+y,
                  [1 if np.isscalar(i) else len(i) for i in y])-len(pfit)+1)

    # uncertainties:
    uncer = {}
    for k in pfix.keys():
        if not k in fitOnly:
            uncer[k]=0 # not fitted, uncertatinties to 0
        else:
            i = fitOnly.index(k)
            if cov is None:
                uncer[k]=-1
            else:
                uncer[k]= np.sqrt(np.abs(np.diag(cov)[i]*reducedChi2))

    if verbose:
        print '-'*20
        print 'REDUCED CHI2=', reducedChi2
        tmp = pfix.keys(); tmp.sort()
        for k in tmp:
            print k, '=', pfix[k],
            if uncer[k]!=0:
                print '+/-', uncer[k]
            else:
                print ''
    # result:
    return pfix, uncer, chi2, model ,  {"reduced_chi2":reducedChi2,"cov":cov,"plsq":plsq,"pfit":pfit,"fitOnly":fitOnly,"bounds":bounds} 
Esempio n. 24
0
print "Standard Least Squares fitting results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier
print ""

# same as above using no bounds
p0 = [1.0, 0.0]
p, cov_x, infodic, mesg, ier = leastsqbound(err,
                                            p0,
                                            args=(y, x),
                                            full_output=True)

# print out results
print "Bounded Least Squares fitting with no bounds results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier
print ""
Esempio n. 25
0
def main():
    #
    # y axis is horizontal
    # z axis is vertical
    #

    #
    #load height profile
    #
    input_file = "tmpHeights.dat"
    a = numpy.loadtxt(input_file)
    y0 = a[:, 0]
    z0 = a[:, 1]
    z0 -= z0.min()

    #
    #load slopes profile
    #
    input_file = "tmpSlopes.dat"
    a = numpy.loadtxt(input_file)
    yp0 = a[:, 0]
    zp0 = a[:, 1]

    L = y0[-1] - y0[0]
    print("Mirror data from file: %s :" % input_file)
    print("    Mirror length is: %.3f m" % L)
    N = y0.size
    print("    Mirror contains %d points" % N)

    slope_error_rms = zp0.std()
    print("    Mirror slope error RMS is  %.3f urad = %.3f arcsec" %
          (slope_error_rms * 1e6, slope_error_rms * 180 / numpy.pi * 3600))

    #
    #aspheric fit
    #

    # fit_method = 0   fit aspherical heights, use curve_fit on heights (NOT WORKING)
    # fit_method = 1   fit aspherical heights, use leastsq on heights (NOT WORKING)
    # fit_method = 2   fit aspherical heights, use bounded leastsq on heights (NOT WORKING)
    # fit_method = 3   fit elliptical heights
    # fit_method = 4   fit elliptical slopes
    # fit_method = 5   fit elliptical heights using Xianbo method

    fit_method = 4

    if fit_method == 0:  # use curve_fit
        popt, pcov = curve_fit(func_aspheric, y0, z0)
        print("popt: ", repr(popt))
        print("pcov: ", repr(pcov))
        z2 = func_aspheric(y0, popt[0], popt[1])

    if fit_method == 1:  # use lestsq
        fitfunc = lambda p, x: func_aspheric(x, p[0], p[1])
        #z2 = fitfunc([radius*1.2,0.0],y0)
        errfunc = lambda p, x, y: fitfunc(p, x) - y
        #z2 = errfunc([radius*1.2,0.0],y0,z0)

        #print(errfunc([radius,0.0],y0,z0))
        p0 = [radius, 0.0]  # initial guess

        #popt, success = leastsq(errfunc, p0[:], args=(y0, z0))
        #print("popt: ",repr(popt))
        #print("success: ",repr(success))

        popt, cov_x, infodic, mesg, ier = leastsq(errfunc,
                                                  p0,
                                                  args=(y0, z0),
                                                  full_output=True)
        print("Standard Least Squares fitting results:")
        print("p0:", p0)
        print("cov_x:", cov_x)
        print("infodic['nfev']:", infodic['nfev'])
        print("infodic['fvec']:", infodic['fvec'])
        print("infodic['fjac']:", infodic['fjac'])
        print("infodic['ipvt']:", infodic['ipvt'])
        print("infodic['qtf']:", infodic['qtf'])
        print("mesg:", mesg)
        print("ier:", ier)
        print(">>>>> popt: ", repr(popt))
        print("")

        z2 = func_aspheric(y0, popt[0], popt[1])

    if fit_method == 2:  # use lestsq
        fitfunc = lambda p, x: func_aspheric(x, p[0], p[1])
        #z2 = fitfunc([radius*1.2,0.0],y0)
        errfunc = lambda p, x, y: fitfunc(p, x) - y
        #z2 = errfunc([radius*1.2,0.0],y0,z0)

        #print(errfunc([radius,0.0],y0,z0))
        p0 = [radius, -0.9999999999]  # initial guess

        # https://github.com/jjhelmus/leastsqbound-scipy
        from leastsqbound import leastsqbound
        bounds = [(radius * 0.5, radius * 1.5), (-1.0, -0.9)]
        popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc,
                                                       p0,
                                                       args=(y0, z0),
                                                       bounds=bounds,
                                                       full_output=True)

        # print out results

        print("Bounded Least Squares fitting with no bounds results:")
        print("p0:", p0)
        print("cov_x:", cov_x)
        print("infodic['nfev']:", infodic['nfev'])
        print("infodic['fvec']:", infodic['fvec'])
        print("infodic['fjac']:", infodic['fjac'])
        print("infodic['ipvt']:", infodic['ipvt'])
        print("infodic['qtf']:", infodic['qtf'])
        print("mesg:", mesg)
        print("ier:", ier)
        print(">>>>> popt: ", repr(popt))
        print("")

        z2 = func_aspheric(y0, popt[0], popt[1])
        #z2 = func_aspheric(y0, popt[0], -0.99999996025050053)

    if fit_method == 3:  # ellipse fitting heights

        ibounded = 0  #=0 curve_fit (no guess), 1=leastsq, 2=bounded

        print("======== Fitting heights =======")

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            popt, cov_x = curve_fit(func_ellipse, y0, z0, maxfev=10000)
        else:
            #dabam-4 (Amparo)
            # p0 = 98.00
            # q0 = 0.0775
            # theta0 = 3.9e-3
            # #
            # #dabam-6 (Soleil) p=499.14 mm q= 4500 mm teta = 34.99 mrad
            p0 = 499.14e-3
            q0 = 4500e-3
            theta0 = 34.99e-3
            # #
            # #dabam-19 #design parameter of ellipse: entrance arm: 420000mm; exit arm: 900mm; angle of incidence 3.052mrad
            # p0 = 420.0
            # q0 = 0.9
            # theta0 =  3.052e-3
            # #
            # #dabam-20 #design parameter of ellipse: entrance arm 9000mm; exit arm: 350mm; angle of incidence: 2.5deg
            # p0 = 9.0
            # q0 = 0.35
            # theta0 =  2.5*numpy.pi/180
            # #TODO:
            # zp0 = -zp0
            # #
            # #dabam-21 #design parameter of ellipse: entrance arm: 7500mm; exit arm: 2500mm; angle of incidence 0.6deg
            # p0 = 7.5
            # q0 = 2.5
            # theta0 =  0.6*numpy.pi/180

            p_guess = [p0, q0, theta0]
            z1 = func_ellipse_amparo(yp0, p_guess[0], p_guess[1], p_guess[2])

            # ishift = 0
            # if ishift:
            #     print(">>>>>>>> slope zp0[0], zp1[0], diff: ",zp0[0],zp1[1],zp0[0]-zp1[1])
            #     print(">>>>>>>>>>>>>>>>>>> shift value: ",(zp0-zp1)[1])
            #     p_guess[3]  = (zp0-zp1)[1]
            #     zp1 = func_ellipse(yp0, p_guess[0], p_guess[1], p_guess[2], p_guess[3])

            print("p0,q0,theta: ", p0, q0, theta0)

            fitfunc_ell_heights = lambda p, x: func_ellipse_amparo(
                x, p[0], p[1], p[2])
            errfunc_ell_heights = lambda p, x, y: fitfunc_ell_heights(p, x) - y

            if ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_heights,
                                                          p_guess,
                                                          args=(y0, z0),
                                                          full_output=True)
            else:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [(p0 * 0.998, p0 * 1.002), (q0 * 0.8, q0 * 1.2),
                          (theta0 * 0.98, theta0 * 1.02)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(
                    errfunc_ell_heights,
                    p_guess,
                    args=(y0, z0),
                    bounds=bounds,
                    full_output=True)

            print("cov_x:", cov_x)
            # print("infodic['nfev']:", infodic['nfev'])
            # print("infodic['fvec']:", infodic['fvec'])
            # print("infodic['fjac']:", infodic['fjac'])
            # print("infodic['ipvt']:", infodic['ipvt'])
            # print("infodic['qtf']:", infodic['qtf'])
            # print("mesg:", mesg)
            # print("ier:", ier)

            print(">>>>> p_guess:", p_guess)
            #zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2], 0.0 ) #p_guess[3]) #TODO!!
            dd = numpy.concatenate((y0, z1), axis=0).reshape(2, -1).transpose()
            outFile = "tmp_z1.dat"
            numpy.savetxt(outFile, dd)
            print("File " + outFile + " written to disk:\n")

        print(">>>>> popt (p,q,theta): ", popt)

        z2 = func_ellipse(y0, popt[0], popt[1], popt[2])
        #amparo z2 = func_ellipse(y0, 98.0, 81.826e-3, 3.865*1e-3)
        if ibounded != 0:
            print('Height error RMS z0-z1:             %.3f nm' %
                  (1e9 * (z0 - z1).std()))
        print('height error RMS z0-z2:             %.3f nm' %
              (1e9 * (z0 - z2).std()))
        dd = numpy.concatenate((y0, z2), axis=0).reshape(2, -1).transpose()
        outFile = "tmp_z2.dat"
        numpy.savetxt(outFile, dd)
        print("File " + outFile + " written to disk:\n")

    if fit_method == 4:  # ellipse, slopes fit

        ibounded = 1  #=0 curve_fit (no guess), 1=leastsq, 2=bounded

        print("======== Fitting slopes =======")

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            popt, cov_x = curve_fit(func_ellipse_slopes,
                                    yp0,
                                    zp0,
                                    maxfev=10000)
        else:
            ishift = 0

            #dabam-4 (Amparo)
            p0 = 98.00
            q0 = 0.0775
            theta0 = 3.9e-3

            # # # #
            # #dabam-6 (Soleil) p=499.14 mm q= 4500 mm teta = 34.99 mrad
            # p0 = 499.14e-3
            # q0 = 4500e-3
            # theta0 = 34.99e-3
            # ishift = 1
            # #
            # #
            # # #
            # #dabam-19 #design parameter of ellipse: entrance arm: 420000mm; exit arm: 900mm; angle of incidence 3.052mrad
            # p0 = 420.0            #WRONG INPUTS?
            # q0 = 0.9              #WRONG INPUTS?
            # theta0 =  3.052e-3    #WRONG INPUTS?
            # # yp0 = yp0 - yp0[int(yp0.size/2)]
            #
            # #
            # #dabam-20 #design parameter of ellipse: entrance arm 9000mm; exit arm: 350mm; angle of incidence: 2.5deg
            # p0 = 9.0
            # q0 = 0.35
            # theta0 =  2.5*numpy.pi/180
            # #TODO:
            # yp0 = yp0 - yp0[int(yp0.size/2)]
            # zp0 = -zp0
            #
            # #
            # #dabam-21 #design parameter of ellipse: entrance arm: 7500mm; exit arm: 2500mm; angle of incidence 0.6deg
            # p0 = 7.5
            # q0 = 2.5
            # theta0 =  0.6*numpy.pi/180
            # ishift = 1

            p_guess = [p0, q0, theta0]
            zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2])

            if ishift:
                zp0 = zp0 + (zp1[0] - zp0[0])

            print("p0,q0,theta: ", p0, q0, theta0)

            fitfunc_ell_slopes = lambda p, x: func_ellipse_slopes(
                x, p[0], p[1], p[2])
            errfunc_ell_slopes = lambda p, x, y: fitfunc_ell_slopes(p, x) - y

            if ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_slopes,
                                                          p_guess,
                                                          args=(yp0, zp0),
                                                          full_output=True)
            elif ibounded == 2:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [(p0 * 0.998, p0 * 1.002), (q0 * 0.8, q0 * 1.2),
                          (theta0 * 0.98, theta0 * 1.02)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(
                    errfunc_ell_slopes,
                    p_guess,
                    args=(yp0, zp0),
                    bounds=bounds,
                    full_output=True)

            print("cov_x:", cov_x)
            # print("infodic['nfev']:", infodic['nfev'])
            # print("infodic['fvec']:", infodic['fvec'])
            # print("infodic['fjac']:", infodic['fjac'])
            # print("infodic['ipvt']:", infodic['ipvt'])
            # print("infodic['qtf']:", infodic['qtf'])
            # print("mesg:", mesg)
            # print("ier:", ier)

            print(">>>>> p_guess:", p_guess)
            #zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2])
            dd = numpy.concatenate((yp0, zp1), axis=0).reshape(2,
                                                               -1).transpose()
            outFile = "tmp_zp1.dat"
            numpy.savetxt(outFile, dd)
            print("File " + outFile + " written to disk:\n")

        print(">>>>> popt (p,q,theta): ", popt)
        zp2 = func_ellipse_slopes(yp0, popt[0], popt[1], popt[2])
        #amparo  zp2 = func_ellipse_slopes(yp, 98.0, 82.0424e-3, 3.8754e-3, 0.0)

        if ibounded != 0:
            print('Slope error RMS zp0-zp1:             %.3f urad' %
                  (1e6 * (zp0 - zp1).std()))
        print('Slope error RMS zp0-zp2:             %.3f urad' %
              (1e6 * (zp0 - zp2).std()))
        dd = numpy.concatenate((yp0, zp2), axis=0).reshape(2, -1).transpose()
        outFile = "tmp_zp2.dat"
        numpy.savetxt(outFile, dd)
        print("File " + outFile + " written to disk:\n")

    if fit_method == 5:  # ellipse fitting heights using Xianbo method

        ibounded = 2  #=0 curve_fit (no guess), 1=leastsq, 2=bounded

        print("======== Fitting heights =======")

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            popt, cov_x = curve_fit(func_ellipse_xianbo, y0, z0, maxfev=10000)
        else:
            #dabam-4 (Amparo)
            # p0 = 98.00
            # q0 = 0.0775
            # theta0 = 3.9e-3
            # OFFSET = 0.0
            # XC = 0.0
            # #
            # #dabam-6 (Soleil) p=499.14 mm q= 4500 mm teta = 34.99 mrad
            # p0 = 499.14e-3
            # q0 = 4500e-3
            # theta0 = 34.99e-3
            # OFFSET = 0.0
            # XC = 0.0
            # #
            # #dabam-19 #design parameter of ellipse: entrance arm: 420000mm; exit arm: 900mm; angle of incidence 3.052mrad
            # p0 = 420.0
            # q0 = 0.9
            # theta0 =  3.052e-3
            # OFFSET = 0.0
            # XC = 0.0
            # #
            # #dabam-20 #design parameter of ellipse: entrance arm 9000mm; exit arm: 350mm; angle of incidence: 2.5deg
            p0 = 9.0
            q0 = 0.35
            theta0 = 2.5 * numpy.pi / 180
            OFFSET = 0.0
            XC = 75e-3
            # #TODO:
            # zp0 = -zp0
            # #
            # #dabam-21 #design parameter of ellipse: entrance arm: 7500mm; exit arm: 2500mm; angle of incidence 0.6deg
            # p0 = 7.5
            # q0 = 2.5
            # theta0 =  0.6*numpy.pi/180
            # OFFSET = 0.0
            # XC = 0.0

            p_guess = [p0, q0, theta0, OFFSET, XC]
            z1 = func_ellipse_xianbo(yp0, p_guess[0], p_guess[1], p_guess[2],
                                     p_guess[3], p_guess[4])

            # ishift = 0
            # if ishift:
            #     print(">>>>>>>> slope zp0[0], zp1[0], diff: ",zp0[0],zp1[1],zp0[0]-zp1[1])
            #     print(">>>>>>>>>>>>>>>>>>> shift value: ",(zp0-zp1)[1])
            #     p_guess[3]  = (zp0-zp1)[1]
            #     zp1 = func_ellipse(yp0, p_guess[0], p_guess[1], p_guess[2], p_guess[3])

            print("p0,q0,theta,OFFSET,XC: ", p0, q0, theta0, OFFSET, XC)

            fitfunc_ell_heights = lambda p, x: func_ellipse_xianbo(
                x, p[0], p[1], p[2], p[3], p[4])
            errfunc_ell_heights = lambda p, x, y: fitfunc_ell_heights(p, x) - y

            if ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_heights,
                                                          p_guess,
                                                          args=(y0, z0),
                                                          full_output=True)
            else:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [(p0 * 0.998, p0 * 1.002), (q0 * 0.8, q0 * 1.2),
                          (theta0 * 0.98, theta0 * 1.02),
                          (OFFSET * 0.9, OFFSET * 1.2), (XC * 0.9, XC * 1.2)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(
                    errfunc_ell_heights,
                    p_guess,
                    args=(y0, z0),
                    bounds=bounds,
                    full_output=True)

            print("cov_x:", cov_x)
            # print("infodic['nfev']:", infodic['nfev'])
            # print("infodic['fvec']:", infodic['fvec'])
            # print("infodic['fjac']:", infodic['fjac'])
            # print("infodic['ipvt']:", infodic['ipvt'])
            # print("infodic['qtf']:", infodic['qtf'])
            # print("mesg:", mesg)
            # print("ier:", ier)

            print(">>>>> p_guess:", p_guess)
            #zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2], 0.0 ) #p_guess[3]) #TODO!!
            dd = numpy.concatenate((y0, z1), axis=0).reshape(2, -1).transpose()
            outFile = "tmp_z1.dat"
            numpy.savetxt(outFile, dd)
            print("File " + outFile + " written to disk:\n")

        print(">>>>> popt (p,q,theta): ", popt)

        z2 = func_ellipse_xianbo(y0, popt[0], popt[1], popt[2], popt[3],
                                 popt[4])
        #amparo z2 = func_ellipse(y0, 98.0, 81.826e-3, 3.865*1e-3)
        if ibounded != 0:
            print('Height error RMS z0-z1:             %.3f nm' %
                  (1e9 * (z0 - z1).std()))
        print('height error RMS z0-z2:             %.3f nm' %
              (1e9 * (z0 - z2).std()))
        dd = numpy.concatenate((y0, z2), axis=0).reshape(2, -1).transpose()
        outFile = "tmp_z2.dat"
        numpy.savetxt(outFile, dd)
        print("File " + outFile + " written to disk:\n")

    #
    #plots
    #
    do_plots = 1
    if do_plots:
        #
        #plots
        #
        from matplotlib import pylab as plt

        if fit_method == 4:  #slopes
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(yp0 * 1e3, zp0 * 1e6)
            if ibounded != 0: plt.plot(yp0 * 1e3, zp1 * 1e6)
            plt.plot(yp0 * 1e3, zp2 * 1e6)
            plt.title(
                "slopes data (blue), starting (green) and optimized (red) ellipse"
            )
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(yp0 * 1e3, (zp0 - zp2) * 1e6)
            plt.title("residual slopes")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")
        elif (fit_method == 3 or fit_method == 5):  #heights
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0 * 1e3, z0 * 1e6)
            if ibounded != 0: plt.plot(y0 * 1e3, z1 * 1e6)
            plt.plot(y0 * 1e3, z2 * 1e6)
            plt.title(
                "height data (blue), starting (green) and optimized (red) ellipse"
            )
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [um]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0 * 1e3, (z0 - z2) * 1e9)
            plt.title("residual heights")
            plt.xlabel("Y [mm]")
            plt.ylabel("Z [nm]")

        plt.show()
Esempio n. 26
0
    def leastsq(self, x, y, parameters=None, sigma=None):
        logger = logging.getLogger(__name__)
        # Ensure all values of sigma or non zero by replacing with the minimum nonzero value
        if sigma is not None and self.useErrorBars:
            nonzerosigma = sigma[sigma > 0]
            sigma[sigma == 0] = numpy.min(
                nonzerosigma) if len(nonzerosigma) > 0 else 1.0
        else:
            sigma = None
        if parameters is None:
            parameters = [float(param) for param in self.startParameters]
        if self.useSmartStartValues:
            smartParameters = self.smartStartValues(x, y, parameters,
                                                    self.parameterEnabled)
            if smartParameters is not None:
                parameters = [
                    smartparam if enabled else param
                    for enabled, param, smartparam in zip(
                        self.parameterEnabled, parameters, smartParameters)
                ]

        myEnabledBounds = self.enabledBounds()
        if myEnabledBounds:
            enabledOnlyParameters, cov_x, infodict, self.mesg, self.ier = leastsqbound(
                self.residuals,
                self.enabledStartParameters(parameters, bounded=True),
                args=(y, x, sigma),
                epsfcn=self.epsfcn,
                full_output=True,
                bounds=myEnabledBounds)
        else:
            enabledOnlyParameters, cov_x, infodict, self.mesg, self.ier = leastsq(
                self.residuals,
                self.enabledStartParameters(parameters),
                args=(y, x, sigma),
                epsfcn=self.epsfcn,
                full_output=True)
        self.setEnabledFitParameters(enabledOnlyParameters)
        self.update(self.parameters)
        logger.info("chisq {0}".format(sum(infodict["fvec"] *
                                           infodict["fvec"])))

        # calculate final chi square
        self.chisq = sum(infodict["fvec"] * infodict["fvec"])

        self.dof = max(len(x) - len(parameters), 1)
        RMSres = Q(sqrt(self.chisq / self.dof))
        RMSres.significantDigits = 3
        self.results['RMSres'].value = RMSres
        # chisq, sqrt(chisq/dof) agrees with gnuplot
        logger.info("success {0} {1}".format(self.ier, self.mesg))
        logger.info("Converged with chi squared {0}".format(self.chisq))
        logger.info("degrees of freedom, dof {0}".format(self.dof))
        logger.info(
            "RMS of residuals (i.e. sqrt(chisq/dof)) {0}".format(RMSres))
        logger.info("Reduced chisq (i.e. variance of residuals) {0}".format(
            self.chisq / self.dof))

        # uncertainties are calculated as per gnuplot, "fixing" the result
        # for non unit values of the reduced chisq.
        # values at min match gnuplot
        enabledParameterNames = self.enabledParameterNames()
        if cov_x is not None:
            enabledOnlyParametersConfidence = numpy.sqrt(
                numpy.diagonal(cov_x)) * sqrt(self.chisq / self.dof)
            self.setEnabledConfidenceParameters(
                enabledOnlyParametersConfidence)
            logger.info("Fitted parameters at minimum, with 68% C.I.:")
            for i, pmin in enumerate(enabledOnlyParameters):
                logger.info(
                    "%2i %-10s %12f +/- %10f" %
                    (i, enabledParameterNames[i], pmin,
                     sqrt(max(cov_x[i, i], 0)) * sqrt(self.chisq / self.dof)))

            logger.info("Correlation matrix")
            # correlation matrix close to gnuplot
            messagelist = ["               "]
            for i in range(len(enabledOnlyParameters)):
                messagelist.append("%-10s" % (enabledParameterNames[i], ))
            logger.info(" ".join(messagelist))
            messagelist = []
            for i in range(len(enabledOnlyParameters)):
                messagelist.append("%10s" % enabledParameterNames[i])
                for j in range(i + 1):
                    messagelist.append(
                        "%10f" %
                        (cov_x[i, j] / sqrt(abs(cov_x[i, i] * cov_x[j, j])), ))
                logger.info(" ".join(messagelist))

                #-----------------------------------------------
        else:
            self.parametersConfidence = [None] * len(self.parametersConfidence)

        return self.parameters
Esempio n. 27
0
def ellipse_fit(entry_number=21,
                fit_method=1,
                fit_function='dabam',
                ibounded=1,
                do_plots=1):
    """

    :param entry_number: dabam entry number
    :param fit_method: fit elliptical heights (0), fit elliptical slopes (1)
    :param fit_function: 'dabam' , 'amparo', 'xianbo'
    :param ibounded: 0 curve_fit (no guess), 1=leastsq, 2=bounded
    :param do_plot: 1 display plots
    :return:
    """

    #
    #get profiles
    #
    import dabam
    dm = dabam.dabam()
    dm.inputs["entryNumber"] = entry_number
    dm.inputs["setDetrending"] = -1
    dm.load()

    #
    #
    #
    p0 = dm.h["ELLIPSE_DESIGN_P"]
    q0 = dm.h["ELLIPSE_DESIGN_Q"]
    theta0 = dm.h["ELLIPSE_DESIGN_THETA"]

    # y axis is horizonta, z axis is vertical
    y0 = dm.sy
    z0 = dm.zprof
    zp0 = dm.sz

    if fit_method == 0:  # ellipse fitting heights

        hshift = 0.0  #nm
        vshift = 0.0  # nm

        #preprocessors
        if entry_number == 4:
            z0 -= z0.min()
        elif entry_number == 6:
            imin = z0.argmin()
            z0 -= z0[imin]
            y0 -= y0[imin]
            y0 *= -1.0
        elif entry_number == 19:
            pass
        elif entry_number == 20:
            hshift = -15e3
        elif entry_number == 21:
            y0 -= y0[y0.size / 2]

        if fit_function == "amparo":
            fitfunc_ell_heights = lambda p, x: func_ellipse_heights_amparo(
                x, p[0], p[1], p[2], p[3], p[4])
            print("Using function definition: AMPARO")
        elif fit_function == "xianbo":
            fitfunc_ell_heights = lambda p, x: func_ellipse_heights_xianbo(
                x, p[0], p[1], p[2], p[3], p[4])
            print("Using function definition: XIANBO")
        else:
            fitfunc_ell_heights = lambda p, x: func_ellipse_heights_dabam(
                x, p[0], p[1], p[2], p[3], p[4])
            print("Using function definition: DABAM")

        print("======== Fitting heights =======")
        errfunc_ell_heights = lambda p, x, y: fitfunc_ell_heights(p, x) - y

        p_guess = [p0, q0, theta0, hshift, vshift]

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            if fit_function == "amparo":
                popt, cov_x = curve_fit(func_ellipse_heights_amparo,
                                        y0,
                                        z0,
                                        maxfev=10000)
            elif fit_function == "xianbo":
                popt, cov_x = curve_fit(func_ellipse_heights_xianbo,
                                        y0,
                                        z0,
                                        maxfev=10000)
            else:
                popt, cov_x = curve_fit(func_ellipse_heights_dabam,
                                        y0,
                                        z0,
                                        maxfev=10000)
        elif ibounded == 1:
            print("======== Least Squares fitting =======")
            popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_heights,
                                                      p_guess,
                                                      args=(y0, z0),
                                                      full_output=True)
        else:
            print("======== Bounded Least Squares fitting =======")
            # https://github.com/jjhelmus/leastsqbound-scipy
            from leastsqbound import leastsqbound
            bounds = [(p0 * 0.998, p0 * 1.002), (q0 * 0.8, q0 * 1.2),
                      (theta0 * 0.98, theta0 * 1.02), (-0.01, 0.01),
                      (-0.001, 0.001)]
            popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_heights,
                                                           p_guess,
                                                           args=(y0, z0),
                                                           full_output=True,
                                                           bounds=bounds)
        print(">>>>> p_guess:", p_guess)
        print(">>>>> popt:", popt)

        z1 = fitfunc_ell_heights(p_guess, y0)
        z2 = fitfunc_ell_heights(popt, y0)

        zp1 = numpy.gradient(z1, y0[1] - y0[0])
        zp2 = numpy.gradient(z2, y0[1] - y0[0])

        rms_values = (1e9 * (z0 - z1).std(), 1e9 * (z0 - z2).std(),
                      1e6 * numpy.gradient(z0 - z1, y0[1] - y0[0]).std(),
                      1e6 * numpy.gradient(z0 - z2, y0[1] - y0[0]).std())

        print('Height error RMS z0-z1:             %.3f nm' %
              (1e9 * (z0 - z1).std()))
        print('Slope error RMS z0-z1:             %.3f urad' %
              (1e6 * numpy.gradient(z0 - z1, y0[1] - y0[0]).std()))

        print('height error RMS z0-z2:             %.3f nm' %
              (1e9 * (z0 - z2).std()))
        print('Slope error RMS z0-z2:             %.3f urad' %
              (1e6 * numpy.gradient(z0 - z2, y0[1] - y0[0]).std()))

        #dump file
        outFile = "fit.spec"
        f = open(outFile, 'w')
        f.write("#F %s\n" % outFile)
        f.write("\n#S 1 heights profiles\n")
        f.write("#N 5\n")
        f.write(
            "#L coordinate [mm]  heights_orig [um]  ellipse_guess [um]  ellipse_fit [um]  heights-fit [nm]\n"
        )
        for i in range(y0.size):
            f.write("%f %f %f %f %f \n" %
                    (y0[i] * 1e3, z0[i] * 1e6, z1[i] * 1e6, z2[i] * 1e6,
                     (z0[i] - z2[i]) * 1e9))
        f.close()

    if fit_method == 1:  # ellipse, slopes fit

        #preprocessors ellipse fitting slopes
        if entry_number == 4:
            pass
        elif entry_number == 6:
            pass
        elif entry_number == 19:
            pass
        elif entry_number == 20:
            pass
        elif entry_number == 21:
            pass

        if fit_function == "amparo":
            fitfunc_ell_slopes = lambda p, x: func_ellipse_slopes_amparo(
                x, p[0], p[1], p[2], p[3])
        elif fit_function == "dabam":
            fitfunc_ell_slopes = lambda p, x: func_ellipse_slopes_dabam(
                x, p[0], p[1], p[2], p[3])
        else:
            print("Not implemented function: ", fit_function)
            raise NotImplementedError

        print("======== Fitting slopes =======")

        errfunc_ell_slopes = lambda p, x, y: fitfunc_ell_slopes(p, x) - y
        p_guess = [p0, q0, theta0, 0.0]

        zp1 = fitfunc_ell_slopes(p_guess, y0)

        if ibounded == 0:
            print("======== Curve fitting without guess =======")

            if fit_function == "amparo":
                popt, cov_x = curve_fit(func_ellipse_slopes_amparo,
                                        y0,
                                        zp0,
                                        maxfev=10000)
            elif fit_function == "dabam":
                popt, cov_x = curve_fit(func_ellipse_slopes_dabam,
                                        y0,
                                        zp0,
                                        maxfev=10000)
            else:
                print("Not implemented function: ", fit_function)
                raise NotImplementedError

        elif ibounded == 1:
            print("======== Least Squares fitting =======")
            popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_slopes,
                                                      p_guess,
                                                      args=(y0, zp0),
                                                      full_output=True)
        else:
            print("======== Bounded Least Squares fitting =======")
            # https://github.com/jjhelmus/leastsqbound-scipy
            from leastsqbound import leastsqbound
            bounds = [(p0 * 0.9, p0 * 1.1), (q0 * 0.9, q0 * 1.1),
                      (theta0 * 0.9, theta0 * 1.1), (-2.0, 2.0)]
            popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_slopes,
                                                           p_guess,
                                                           args=(y0, zp0),
                                                           bounds=bounds,
                                                           full_output=True)

        print(">>>>> p_guess:", p_guess)
        print(">>>>> popt (p,q,theta): ", popt)

        zp2 = fitfunc_ell_slopes(popt, y0)

        z1 = cdf(y0, zp1)
        z2 = cdf(y0, zp2)

        rms_values = (1e9 * (cdf(y0, zp0 - zp1)).std(),
                      1e9 * (cdf(y0, zp0 - zp2)).std(),
                      1e6 * (zp0 - zp1).std(), 1e6 * (zp0 - zp2).std())

        print('Height error RMS z0-z1:            %.3f nm' %
              (1e9 * (cdf(y0, zp0 - zp1)).std()))
        print('Slope error RMS zp0-zp1:             %.3f urad' %
              (1e6 * (zp0 - zp1).std()))

        print('Height error RMS z0-z2:            %.3f nm' %
              (1e9 * (cdf(y0, zp0 - zp2)).std()))
        print('Slope error RMS zp0-zp2:             %.3f urad' %
              (1e6 * (zp0 - zp2).std()))

        #dump file
        outFile = "fit.spec"
        f = open(outFile, 'w')
        f.write("#F %s\n" % outFile)
        f.write("\n#S 1 slopes profiles\n")
        f.write("#N 5\n")
        f.write(
            "#L coordinate [mm]  slopes_orig [urad]  ellipse_guess [urad]  ellipse_fit [urad]  slopes-fit [nrad]\n"
        )
        for i in range(y0.size):
            f.write("%f %f %f %f %f \n" %
                    (y0[i] * 1e3, zp0[i] * 1e6, zp1[i] * 1e6, zp2[i] * 1e6,
                     (zp0[i] - zp2[i]) * 1e9))
        f.close()

        print(">>>>> popt (p,q,theta): ", popt)

        rms_values = (1e9 * (z0 - z1).std(), 1e9 * (z0 - z2).std(),
                      1e6 * numpy.gradient(z0 - z1, y0[1] - y0[0]).std(),
                      1e6 * numpy.gradient(z0 - z2, y0[1] - y0[0]).std())

        if ibounded != 0:
            print('Height error RMS z0-z1:             %.3f nm' %
                  (1e9 * (z0 - z1).std()))
        print('height error RMS z0-z2:             %.3f nm' %
              (1e9 * (z0 - z2).std()))
        dd = numpy.concatenate((y0, z2), axis=0).reshape(2, -1).transpose()
        outFile = "tmp_z2.dat"
        numpy.savetxt(outFile, dd)
        print("File " + outFile + " written to disk:\n")

    #
    #plots
    #
    if do_plots:
        #
        #plots
        #
        from matplotlib import pylab as plt

        if (fit_method == 0):  #heights
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0 * 1e3, z0 * 1e6)
            plt.plot(y0 * 1e3, z1 * 1e6)
            plt.plot(y0 * 1e3, z2 * 1e6)
            plt.title(
                "height data (blue), starting (green) and optimized (red) ellipse"
            )
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [um]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0 * 1e3, (z0 - z2) * 1e9)
            plt.title("residual heights")
            plt.xlabel("Y [mm]")
            plt.ylabel("Z [nm]")
        elif fit_method == 1:  #slopes
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0 * 1e3, zp0 * 1e6)
            if ibounded != 0: plt.plot(y0 * 1e3, zp1 * 1e6)
            plt.plot(y0 * 1e3, zp2 * 1e6)
            plt.title(
                "slopes data (blue), starting (green) and optimized (red) ellipse"
            )
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0 * 1e3, (zp0 - zp2) * 1e6)
            plt.title("residual slopes")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")

        plt.show()

    return rms_values
Esempio n. 28
0
def LevMar(func,
           par,
           func_args,
           y,
           err=None,
           fixed=None,
           bounds=None,
           return_BIC=False,
           return_AIC=False,
           verbose=True,
           fix_noise=False):  #,maxiter=10000, maxfun=10000, verbose=True):
    """
  Function wrapper for Levenberg-Marquardt via scipy.optimize.least_sq
  
  Similar interface to Optimiser.py to allow for fixed parameters. I have included
  code from https://github.com/jjhelmus/leastsqbound-scipy/ in order to implement the
  bound case (leastsqbound), else defaults to least_squares
  
  Has a similar syntax to Optimiser, but requires the function to be passed rather than
  the likelihood function (therefore cannot optimise noise parameters, GPs etc). Added
  leastsqbound (from https://github.com/jjhelmus/leastsqbound-scipy/, Copyright (c) 2012
  Jonathan J. Helmus, see file for full license) that uses parameter transformations to
  enable bound optimisation. This is only enabled for bound optimisation. The error
  estimates from LM optimisation are useful to seed MCMC, and also can be used to compute
  an evidence approximation (via BIC, AIC or Laplace optimisation). Care needs to be taken
  as to the reliability of the uncertainties compared to an MCMC, and this should
  generally only be used as an approximation.
  
  Parameters
  ----------
  func : function to fit
  par : parameters of function
  func_args : arguments to function
  y : measurements
  err : uncertainties for each measurement, defaults to array of ones
  fixed : array of fixed parameters
  bounds : array of boundaries (min,max) pairs for each parameter, array (N_param x 2)
    - input None where for no lower/upper boundary. bounds = None uses std leastsq
  return_BIC : return BIC evidence estimate
  return_AIC : return AIC evidence estimate
  fix_noise : if True, don't rescale errorbars according to chi2
  
  Returns
  -------
  bf_par : fitted parameter vector
  err_par : uncertainty estimate for each parameter
  rescale : rescale value for errors, equivalent to white noise estimate for err = 1
      std of the residuals in this case, or if err provided a rescale to get true noise
  K_fit : covariance matrix of the fitted parameters (should edit to include non-fitted terms?)
      edits will be needed to use in laplace optimisation of alpha parameters...
  logE : evidence approximation from Laplace approximation
  logE_BIC : evidence approximation from BIC (optional)
  logE_AIC : evidence approximation from AIC (optional)
  
  """

    #make variable and fixed par arrays
    if fixed is None:
        var_par = np.copy(par)
        fixed_par = None
    #otherwise construct the parameter vector from var_par and fixed_par_val
    else:
        par = np.array(par)
        fixed = np.array(fixed)  #ensure fixed is a np array
        #assign parameters to normal param vector
        fixed_par = par[np.where(fixed == True)]
        var_par = par[np.where(fixed != True)]

    #set error vector if not provided
    if err is None: err = np.ones(y.size)
    else: err = err * np.ones(y.size)

    #get the bounds for variable parameters
    if bounds is None:
        bounds_var = None
    else:
        bounds_var = bounds[np.where(fixed != True)]

    #perform the optimisation:
    #if bounds is None: R = leastsq(LM_ErrFunc,var_par,(func,func_args,y,err,fixed,fixed_par),full_output=1)
    if bounds is None:
        R = least_squares(LM_ErrFunc,
                          var_par,
                          args=(func, func_args, y, err, fixed, fixed_par),
                          method='trf',
                          verbose=0)
        fitted_par = R.x
        H = np.dot(R.jac.T, R.jac)  #hessian matrix
        K_fit = np.linalg.inv(H)  #covariance matrix
        nfev = R.nfev
    else:
        R = leastsqbound(LM_ErrFunc,
                         var_par, (func, func_args, y, err, fixed, fixed_par),
                         bounds=bounds_var,
                         full_output=1)
        fitted_par = R[0]
        K_fit = R[1]
        nfev = R[2]['nfev']

    #reconstruct the full parameter vector and covariance matrix
    if fixed is None:
        bf_par = fitted_par
        return_err = np.sqrt(np.diag(K_fit))
        err_par = np.sqrt(np.diag(K_fit))
        K = K_fit
    else:
        bf_par = np.copy(par)
        bf_par[np.where(fixed != True)] = fitted_par
        err_par = np.zeros(par.size)
        err_par[np.where(fixed != True)] = np.sqrt(np.diag(K_fit))
        K = K_fit

    #rescale errors and covariance
    rescale = np.std((y - func(bf_par, *func_args)) / err)
    if not fix_noise:
        K_fit *= rescale**2
        err_par *= rescale

    #estimate the white noise from the residuals
    resid = y - func(bf_par, *func_args)
    wn = np.std(resid)

    if verbose:
        print "-" * 80
        print "LM fit parameter estimates: (function evals: {})".format(nfev)
        print " par = mean +- err"
        for i in range(bf_par.size):
            print " p[{}] = {:.8f} +- {:.8f}".format(i, bf_par[i], err_par[i])
        print "white noise =", wn

    #calculate the log evidence for the best fit model
    if fix_noise: logP_max = LogLikelihood_iid(resid, 1., err)
    else: logP_max = LogLikelihood_iid(resid, 1., err * rescale)
    D = np.diag(K_fit).size
    N_obs = y.size
    logE_BIC = logP_max - D / 2. * np.log(N_obs)
    logE_AIC = logP_max - D * N_obs / (N_obs - D - 1.)
    sign, logdetK = np.linalg.slogdet(2 * np.pi * K_fit)  # get log determinant
    logE = logP_max + 0.5 * logdetK  #get evidence approximation based on Gaussian assumption

    if fixed is None or fixed.sum() == 0:
        Kn = K
    else:  #expand K to the complete covariance matrix - ie even fixed parameters + white noise
        ind = np.hstack([(fixed == 0).cumsum()[np.where(fixed == 1)],
                         K.diagonal().size])  #get index to insert zeros
        Kn = np.insert(np.insert(K, ind, 0, axis=0), ind, 0,
                       axis=1)  #insert zeros corresponding to fixed pars

    if verbose:
        print "Gaussian Evidence approx:"
        print " log ML =", logP_max
        print " log E =", logE
        print " log E (BIC) =", logE_BIC, "(D = {}, N = {})".format(D, N_obs)
        print " log E (AIC) =", logE_AIC, "(D = {}, N = {})".format(D, N_obs)
        print "-" * 80

    ret_list = [bf_par, err_par, rescale, Kn, logE]
    if return_BIC: ret_list.append(logE_BIC)
    if return_AIC: ret_list.append(logE_AIC)
    return ret_list
Esempio n. 29
0
def ellipse_fit(entry_number = 21, fit_method=1, fit_function='dabam', ibounded=1,do_plots=1):
    """

    :param entry_number: dabam entry number
    :param fit_method: fit elliptical heights (0), fit elliptical slopes (1)
    :param fit_function: 'dabam' , 'amparo', 'xianbo'
    :param ibounded: 0 curve_fit (no guess), 1=leastsq, 2=bounded
    :param do_plot: 1 display plots
    :return:
    """

    #
    #get profiles
    #
    import dabam
    dm = dabam.dabam()
    dm.inputs["entryNumber"] = entry_number
    dm.inputs["setDetrending"] = -1
    dm.load()

    #
    #
    #
    p0 = dm.h["ELLIPSE_DESIGN_P"]
    q0 = dm.h["ELLIPSE_DESIGN_Q"]
    theta0 = dm.h["ELLIPSE_DESIGN_THETA"]

    # y axis is horizonta, z axis is vertical
    y0  = dm.sy
    z0  = dm.zprof
    zp0 = dm.sz

    if fit_method == 0: # ellipse fitting heights

        hshift = 0.0 #nm
        vshift = 0.0 # nm

        #preprocessors
        if entry_number == 4:
            z0 -= z0.min()
        elif entry_number == 6:
            imin = z0.argmin()
            z0 -= z0[imin]
            y0 -= y0[imin]
            y0 *= -1.0
        elif entry_number == 19:
            pass
        elif entry_number == 20:
            hshift = -15e3
        elif entry_number == 21:
            y0 -= y0[y0.size/2]


        if fit_function == "amparo":
            fitfunc_ell_heights = lambda p, x: func_ellipse_heights_amparo(x, p[0], p[1], p[2], p[3], p[4])
            print("Using function definition: AMPARO")
        elif fit_function == "xianbo":
            fitfunc_ell_heights = lambda p, x: func_ellipse_heights_xianbo(x, p[0], p[1], p[2], p[3], p[4])
            print("Using function definition: XIANBO")
        else:
            fitfunc_ell_heights = lambda p, x: func_ellipse_heights_dabam(x, p[0], p[1], p[2], p[3], p[4])
            print("Using function definition: DABAM")

        print("======== Fitting heights =======")
        errfunc_ell_heights = lambda p, x, y: fitfunc_ell_heights(p, x) - y

        p_guess = [p0,q0,theta0,hshift,vshift]

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            if fit_function == "amparo":
                popt, cov_x = curve_fit(func_ellipse_heights_amparo, y0, z0, maxfev=10000)
            elif fit_function == "xianbo":
                popt, cov_x = curve_fit(func_ellipse_heights_xianbo, y0, z0, maxfev=10000)
            else:
                popt, cov_x = curve_fit(func_ellipse_heights_dabam, y0, z0, maxfev=10000)
        elif ibounded == 1:
            print("======== Least Squares fitting =======")
            popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_heights, p_guess,args=(y0, z0), full_output=True)
        else:
            print("======== Bounded Least Squares fitting =======")
            # https://github.com/jjhelmus/leastsqbound-scipy
            from leastsqbound import leastsqbound
            bounds = [ (p0*0.998,p0*1.002) , (q0*0.8,q0*1.2), (theta0*0.98,theta0*1.02), (-0.01,0.01), (-0.001,0.001)]
            popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_heights, p_guess,
                                                           args=(y0,z0), full_output=True, bounds=bounds)
        print(">>>>> p_guess:", p_guess)
        print(">>>>> popt:", popt)

        z1 = fitfunc_ell_heights(p_guess, y0)
        z2 = fitfunc_ell_heights(popt, y0)

        zp1 = numpy.gradient(z1,y0[1]-y0[0])
        zp2 = numpy.gradient(z2,y0[1]-y0[0])


        rms_values = ( 1e9*(z0-z1).std(),1e9*(z0-z2).std(),
                       1e6*numpy.gradient(z0-z1,y0[1]-y0[0]).std(),1e6*numpy.gradient(z0-z2,y0[1]-y0[0]).std())

        print ('Height error RMS z0-z1:             %.3f nm'%(1e9*(z0-z1).std()))
        print ('Slope error RMS z0-z1:             %.3f urad'%(1e6*numpy.gradient(z0-z1,y0[1]-y0[0]).std()))

        print ('height error RMS z0-z2:             %.3f nm'%(1e9*(z0-z2).std()))
        print ('Slope error RMS z0-z2:             %.3f urad'%(1e6*numpy.gradient(z0-z2,y0[1]-y0[0]).std()))

        #dump file
        outFile = "fit.spec"
        f = open(outFile,'w')
        f.write("#F %s\n"%outFile)
        f.write("\n#S 1 heights profiles\n")
        f.write("#N 5\n")
        f.write("#L coordinate [mm]  heights_orig [um]  ellipse_guess [um]  ellipse_fit [um]  heights-fit [nm]\n")
        for i in range(y0.size):
            f.write("%f %f %f %f %f \n"%(y0[i]*1e3,z0[i]*1e6,z1[i]*1e6,z2[i]*1e6,(z0[i]-z2[i])*1e9))
        f.close()


    if fit_method == 1: # ellipse, slopes fit

        #preprocessors ellipse fitting slopes
        if entry_number == 4:
            pass
        elif entry_number == 6:
            pass
        elif entry_number == 19:
            pass
        elif entry_number == 20:
            pass
        elif entry_number == 21:
            pass

        if fit_function == "amparo":
            fitfunc_ell_slopes  =  lambda p, x: func_ellipse_slopes_amparo(x, p[0], p[1], p[2], p[3])
        elif fit_function == "dabam":
            fitfunc_ell_slopes  =  lambda p, x: func_ellipse_slopes_dabam(x, p[0], p[1], p[2], p[3])
        else:
            print("Not implemented function: ",fit_function)
            raise NotImplementedError

        print("======== Fitting slopes =======")

        errfunc_ell_slopes = lambda p, x, y: fitfunc_ell_slopes(p, x) - y
        p_guess = [p0,q0,theta0,0.0]

        zp1 = fitfunc_ell_slopes(p_guess, y0)

        if ibounded == 0:
            print("======== Curve fitting without guess =======")

            if fit_function == "amparo":
                popt, cov_x = curve_fit(func_ellipse_slopes_amparo, y0, zp0, maxfev=10000)
            elif fit_function == "dabam":
                popt, cov_x = curve_fit(func_ellipse_slopes_dabam, y0, zp0, maxfev=10000)
            else:
                print("Not implemented function: ",fit_function)
                raise NotImplementedError

        elif ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_slopes, p_guess, args=(y0, zp0),
                                                          full_output=True)
        else:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [ (p0*0.9,p0*1.1) , (q0*0.9,q0*1.1), (theta0*0.9,theta0*1.1), (-2.0,2.0)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_slopes, p_guess, args=(y0,zp0),
                                                            bounds=bounds,full_output=True)

        print(">>>>> p_guess:", p_guess)
        print(">>>>> popt (p,q,theta): ",popt)

        zp2 = fitfunc_ell_slopes(popt, y0)

        z1 = cdf(y0,zp1)
        z2 = cdf(y0,zp2)

        rms_values = (1e9*(cdf(y0,zp0-zp1)).std(),1e9*(cdf(y0,zp0-zp2)).std(),
                      1e6*(zp0-zp1).std(),1e6*(zp0-zp2).std() )

        print ('Height error RMS z0-z1:            %.3f nm'%(1e9*(cdf(y0,zp0-zp1)).std()))
        print ('Slope error RMS zp0-zp1:             %.3f urad'%(1e6*(zp0-zp1).std()))

        print ('Height error RMS z0-z2:            %.3f nm'%(1e9*(cdf(y0,zp0-zp2)).std()))
        print ('Slope error RMS zp0-zp2:             %.3f urad'%(1e6*(zp0-zp2).std()))

        #dump file
        outFile = "fit.spec"
        f = open(outFile,'w')
        f.write("#F %s\n"%outFile)
        f.write("\n#S 1 slopes profiles\n")
        f.write("#N 5\n")
        f.write("#L coordinate [mm]  slopes_orig [urad]  ellipse_guess [urad]  ellipse_fit [urad]  slopes-fit [nrad]\n")
        for i in range(y0.size):
            f.write("%f %f %f %f %f \n"%(y0[i]*1e3,zp0[i]*1e6,zp1[i]*1e6,zp2[i]*1e6,(zp0[i]-zp2[i])*1e9))
        f.close()

        print(">>>>> popt (p,q,theta): ",popt)


        rms_values = ( 1e9*(z0-z1).std(),1e9*(z0-z2).std(),
           1e6*numpy.gradient(z0-z1,y0[1]-y0[0]).std(),1e6*numpy.gradient(z0-z2,y0[1]-y0[0]).std())

        if ibounded != 0: print ('Height error RMS z0-z1:             %.3f nm'%(1e9*(z0-z1).std()))
        print ('height error RMS z0-z2:             %.3f nm'%(1e9*(z0-z2).std()))
        dd=numpy.concatenate( (y0, z2) ,axis=0).reshape(2,-1).transpose()
        outFile = "tmp_z2.dat"
        numpy.savetxt(outFile,dd)
        print ("File "+outFile+" written to disk:\n")

    #
    #plots
    #
    if do_plots:
        #
        #plots
        #
        from matplotlib import pylab as plt


        if (fit_method == 0): #heights
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0*1e3,z0*1e6)
            plt.plot(y0*1e3,z1*1e6)
            plt.plot(y0*1e3,z2*1e6)
            plt.title("height data (blue), starting (green) and optimized (red) ellipse")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [um]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0*1e3,(z0-z2)*1e9)
            plt.title("residual heights")
            plt.xlabel("Y [mm]")
            plt.ylabel("Z [nm]")
        elif fit_method == 1: #slopes
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0*1e3,zp0*1e6)
            if ibounded != 0: plt.plot(y0*1e3,zp1*1e6)
            plt.plot(y0*1e3,zp2*1e6)
            plt.title("slopes data (blue), starting (green) and optimized (red) ellipse")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0*1e3,(zp0-zp2)*1e6)
            plt.title("residual slopes")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")


        plt.show()


    return rms_values
Esempio n. 30
0
def LevMar(func,par,func_args,y,err=None,fixed=None,bounds=None,return_BIC=False,return_AIC=False,verbose=True):#,maxiter=10000, maxfun=10000, verbose=True):
  """
  Function wrapper for Levenberg-Marquardt via scipy.optimize.least_sq
  
  Similar interface to Optimiser.py to allow for fixed parameters. I have included
  code from https://github.com/jjhelmus/leastsqbound-scipy/ in order to implement the
  bound case (leastsqbound), else defaults to least_squares
  
  Has a similar syntax to Optimiser, but requires the function to be passed rather than
  the likelihood function (therefore cannot optimise noise parameters, GPs etc). Added
  leastsqbound (from https://github.com/jjhelmus/leastsqbound-scipy/, Copyright (c) 2012
  Jonathan J. Helmus, see file for full license) that uses parameter transformations to
  enable bound optimisation. This is only enabled for bound optimisation. The error
  estimates from LM optimisation are useful to seed MCMC, and also can be used to compute
  an evidence approximation (via BIC, AIC or Laplace optimisation). Care needs to be taken
  as to the reliability of the uncertainties compared to an MCMC, and this should
  generally only be used as an approximation.
  
  Parameters
  ----------
  func : function to fit
  par : parameters of function
  func_args : arguments to function
  y : measurements
  err : uncertainties for each measurement, defaults to array of ones
  fixed : array of fixed parameters
  bounds : array of boundaries (min,max) pairs for each parameter, array (N_param x 2)
    - input None where for no lower/upper boundary. bounds = None uses std leastsq
  return_BIC : return BIC evidence estimate
  return_AIC : return AIC evidence estimate
  
  Returns
  -------
  bf_par : fitted parameter vector
  err_par : uncertainty estimate for each parameter
  rescale : rescale value for errors, equivalent to white noise estimate for err = 1
      std of the residuals in this case, or if err provided a rescale to get true noise
  K_fit : covariance matrix of the fitted parameters (should edit to include non-fitted terms?)
      edits will be needed to use in laplace optimisation of alpha parameters...
  logE : evidence approximation from Laplace approximation
  logE_BIC : evidence approximation from BIC (optional)
  logE_AIC : evidence approximation from AIC (optional)
  
  """
  
  #make variable and fixed par arrays
  if fixed is None:
    var_par = np.copy(par)
    fixed_par = None
  #otherwise construct the parameter vector from var_par and fixed_par_val
  else:
    par = np.array(par)
    fixed = np.array(fixed) #ensure fixed is a np array
    #assign parameters to normal param vector
    fixed_par = par[np.where(fixed==True)]
    var_par = par[np.where(fixed!=True)]
  
  #set error vector if not provided
  if err is None: err = np.ones(y.size)
  else: err = err * np.ones(y.size)
  
  #get the bounds for variable parameters
  if bounds is None:
    bounds_var = None
  else:
    bounds_var = bounds[np.where(fixed!=True)]
  
  #perform the optimisation:
  #if bounds is None: R = leastsq(LM_ErrFunc,var_par,(func,func_args,y,err,fixed,fixed_par),full_output=1)
  if bounds is None:
    R = least_squares(LM_ErrFunc,var_par,args=(func,func_args,y,err,fixed,fixed_par),method='trf',verbose=0)
    fitted_par = R.x
    H = np.dot(R.jac.T,R.jac) #hessian matrix
    K_fit = np.linalg.inv(H) #covariance matrix
    nfev = R.nfev
  else:
    R = leastsqbound(LM_ErrFunc,var_par,(func,func_args,y,err,fixed,fixed_par),bounds=bounds_var,full_output=1)
    fitted_par = R[0]
    K_fit = R[1]
    nfev = R[2]['nfev']
  
  #reconstruct the full parameter vector and covariance matrix
  if fixed is None:
    bf_par = fitted_par
    return_err = np.sqrt(np.diag(K_fit))
    err_par = np.sqrt(np.diag(K_fit))
    K = K_fit
  else:
    bf_par = np.copy(par)    
    bf_par[np.where(fixed!=True)] = fitted_par
    err_par = np.zeros(par.size)
    err_par[np.where(fixed!=True)] = np.sqrt(np.diag(K_fit))
    K = K_fit
  
  #rescale errors and covariance
  rescale = np.std((y - func(bf_par,*func_args)) / err)
  K_fit *= rescale**2
  err_par *= rescale
  
  #estimate the white noise from the residuals
  resid = y - func(bf_par,*func_args)
  wn = np.std(resid)
  
  if verbose:
    print "-"*80
    print "LM fit parameter estimates: (function evals: {})".format(nfev)
    print " par = mean +- err"
    for i in range(bf_par.size): print " p[{}] = {:.8f} +- {:.8f}".format(i,bf_par[i],err_par[i])
    print "white noise =", wn
  
  #calculate the log evidence for the best fit model
  logP_max = LogLikelihood_iid(resid,1.,err*rescale)
  D = np.diag(K_fit).size
  N_obs = y.size
  logE_BIC = logP_max - D/2.*np.log(N_obs)
  logE_AIC = logP_max - D * N_obs / (N_obs-D-1.)
  sign,logdetK = np.linalg.slogdet( 2*np.pi*K_fit ) # get log determinant
  logE = logP_max + 0.5 * logdetK #get evidence approximation based on Gaussian assumption
  
  if fixed is None or fixed.sum()==0:
    Kn = K
  else: #expand K to the complete covariance matrix - ie even fixed parameters + white noise
    ind = np.hstack([(fixed==0).cumsum()[np.where(fixed==1)],K.diagonal().size]) #get index to insert zeros
    Kn = np.insert(np.insert(K,ind,0,axis=0),ind,0,axis=1) #insert zeros corresponding to fixed pars
  
  if verbose:
    print "Gaussian Evidence approx:"
    print " log ML =", logP_max
    print " log E =", logE
    print " log E (BIC) =", logE_BIC, "(D = {}, N = {})".format(D,N_obs)
    print " log E (AIC) =", logE_AIC, "(D = {}, N = {})".format(D,N_obs)
    print "-"*80
  
  ret_list = [bf_par,err_par,rescale,Kn,logE]
  if return_BIC: ret_list.append(logE_BIC)
  if return_AIC: ret_list.append(logE_AIC)
  return ret_list
Esempio n. 31
0
def main():
    #
    # y axis is horizontal
    # z axis is vertical
    #

    #
    #load height profile
    #
    input_file = "tmpHeights.dat"
    a = numpy.loadtxt(input_file)
    y0 = a[:,0]
    z0 = a[:,1]
    z0 -= z0.min()

    #
    #load slopes profile
    #
    input_file = "tmpSlopes.dat"
    a = numpy.loadtxt(input_file)
    yp0 = a[:,0]
    zp0 = a[:,1]

    L = y0[-1]-y0[0]
    print("Mirror data from file: %s :"%input_file)
    print("    Mirror length is: %.3f m"%L)
    N = y0.size
    print("    Mirror contains %d points"%N)

    slope_error_rms = zp0.std()
    print("    Mirror slope error RMS is  %.3f urad = %.3f arcsec"%(slope_error_rms*1e6,slope_error_rms*180/numpy.pi*3600))


    #
    #aspheric fit
    #

    # fit_method = 0   fit aspherical heights, use curve_fit on heights (NOT WORKING)
    # fit_method = 1   fit aspherical heights, use leastsq on heights (NOT WORKING)
    # fit_method = 2   fit aspherical heights, use bounded leastsq on heights (NOT WORKING)
    # fit_method = 3   fit elliptical heights
    # fit_method = 4   fit elliptical slopes
    # fit_method = 5   fit elliptical heights using Xianbo method

    fit_method = 4

    if fit_method == 0: # use curve_fit
        popt, pcov = curve_fit(func_aspheric, y0, z0)
        print("popt: ",repr(popt))
        print("pcov: ",repr(pcov))
        z2 = func_aspheric(y0, popt[0], popt[1])


    if fit_method == 1: # use lestsq
        fitfunc = lambda p, x: func_aspheric(x, p[0], p[1])
        #z2 = fitfunc([radius*1.2,0.0],y0)
        errfunc = lambda p, x, y: fitfunc(p, x) - y
        #z2 = errfunc([radius*1.2,0.0],y0,z0)


        #print(errfunc([radius,0.0],y0,z0))
        p0 = [radius, 0.0] # initial guess

        #popt, success = leastsq(errfunc, p0[:], args=(y0, z0))
        #print("popt: ",repr(popt))
        #print("success: ",repr(success))

        popt, cov_x, infodic, mesg, ier = leastsq(errfunc, p0, args=(y0, z0), full_output=True)
        print("Standard Least Squares fitting results:")
        print("p0:", p0)
        print("cov_x:", cov_x)
        print("infodic['nfev']:", infodic['nfev'])
        print("infodic['fvec']:", infodic['fvec'])
        print("infodic['fjac']:", infodic['fjac'])
        print("infodic['ipvt']:", infodic['ipvt'])
        print("infodic['qtf']:", infodic['qtf'])
        print("mesg:", mesg)
        print("ier:", ier)
        print(">>>>> popt: ",repr(popt))
        print("")

        z2 = func_aspheric(y0, popt[0], popt[1])

    if fit_method == 2: # use lestsq
        fitfunc = lambda p, x: func_aspheric(x, p[0], p[1])
        #z2 = fitfunc([radius*1.2,0.0],y0)
        errfunc = lambda p, x, y: fitfunc(p, x) - y
        #z2 = errfunc([radius*1.2,0.0],y0,z0)

        #print(errfunc([radius,0.0],y0,z0))
        p0 = [radius, -0.9999999999] # initial guess

        # https://github.com/jjhelmus/leastsqbound-scipy
        from leastsqbound import leastsqbound
        bounds = [(radius*0.5, radius*1.5), (-1.0, -0.9)]
        popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc, p0, args=(y0,z0),
                                                    bounds=bounds,full_output=True)

        # print out results

        print("Bounded Least Squares fitting with no bounds results:")
        print("p0:", p0)
        print("cov_x:", cov_x)
        print("infodic['nfev']:", infodic['nfev'])
        print("infodic['fvec']:", infodic['fvec'])
        print("infodic['fjac']:", infodic['fjac'])
        print("infodic['ipvt']:", infodic['ipvt'])
        print("infodic['qtf']:", infodic['qtf'])
        print("mesg:", mesg)
        print("ier:", ier)
        print(">>>>> popt: ",repr(popt))
        print("")

        z2 = func_aspheric(y0, popt[0], popt[1])
        #z2 = func_aspheric(y0, popt[0], -0.99999996025050053)


    if fit_method == 3: # ellipse fitting heights

        ibounded = 0 #=0 curve_fit (no guess), 1=leastsq, 2=bounded

        print("======== Fitting heights =======")

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            popt, cov_x = curve_fit(func_ellipse, y0, z0, maxfev=10000)
        else:
            #dabam-4 (Amparo)
            # p0 = 98.00
            # q0 = 0.0775
            # theta0 = 3.9e-3
            # #
            # #dabam-6 (Soleil) p=499.14 mm q= 4500 mm teta = 34.99 mrad
            p0 = 499.14e-3
            q0 = 4500e-3
            theta0 = 34.99e-3
            # #
            # #dabam-19 #design parameter of ellipse: entrance arm: 420000mm; exit arm: 900mm; angle of incidence 3.052mrad
            # p0 = 420.0
            # q0 = 0.9
            # theta0 =  3.052e-3
            # #
            # #dabam-20 #design parameter of ellipse: entrance arm 9000mm; exit arm: 350mm; angle of incidence: 2.5deg
            # p0 = 9.0
            # q0 = 0.35
            # theta0 =  2.5*numpy.pi/180
            # #TODO:
            # zp0 = -zp0
            # #
            # #dabam-21 #design parameter of ellipse: entrance arm: 7500mm; exit arm: 2500mm; angle of incidence 0.6deg
            # p0 = 7.5
            # q0 = 2.5
            # theta0 =  0.6*numpy.pi/180

            p_guess = [p0,q0,theta0]
            z1 = func_ellipse_amparo(yp0, p_guess[0], p_guess[1], p_guess[2])

            # ishift = 0
            # if ishift:
            #     print(">>>>>>>> slope zp0[0], zp1[0], diff: ",zp0[0],zp1[1],zp0[0]-zp1[1])
            #     print(">>>>>>>>>>>>>>>>>>> shift value: ",(zp0-zp1)[1])
            #     p_guess[3]  = (zp0-zp1)[1]
            #     zp1 = func_ellipse(yp0, p_guess[0], p_guess[1], p_guess[2], p_guess[3])

            print("p0,q0,theta: ",p0,q0,theta0)

            fitfunc_ell_heights = lambda p, x: func_ellipse_amparo(x, p[0], p[1], p[2])
            errfunc_ell_heights = lambda p, x, y: fitfunc_ell_heights(p, x) - y

            if ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_heights, p_guess, args=(y0, z0),
                                                          full_output=True)
            else:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [ (p0*0.998,p0*1.002) , (q0*0.8,q0*1.2), (theta0*0.98,theta0*1.02)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_heights, p_guess, args=(y0,z0),
                                                            bounds=bounds,full_output=True)


            print("cov_x:", cov_x)
            # print("infodic['nfev']:", infodic['nfev'])
            # print("infodic['fvec']:", infodic['fvec'])
            # print("infodic['fjac']:", infodic['fjac'])
            # print("infodic['ipvt']:", infodic['ipvt'])
            # print("infodic['qtf']:", infodic['qtf'])
            # print("mesg:", mesg)
            # print("ier:", ier)

            print(">>>>> p_guess:", p_guess)
            #zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2], 0.0 ) #p_guess[3]) #TODO!!
            dd=numpy.concatenate( (y0, z1) ,axis=0).reshape(2,-1).transpose()
            outFile = "tmp_z1.dat"
            numpy.savetxt(outFile,dd)
            print ("File "+outFile+" written to disk:\n")



        print(">>>>> popt (p,q,theta): ",popt)

        z2 = func_ellipse(y0, popt[0], popt[1], popt[2])
        #amparo z2 = func_ellipse(y0, 98.0, 81.826e-3, 3.865*1e-3)
        if ibounded != 0: print ('Height error RMS z0-z1:             %.3f nm'%(1e9*(z0-z1).std()))
        print ('height error RMS z0-z2:             %.3f nm'%(1e9*(z0-z2).std()))
        dd=numpy.concatenate( (y0, z2) ,axis=0).reshape(2,-1).transpose()
        outFile = "tmp_z2.dat"
        numpy.savetxt(outFile,dd)
        print ("File "+outFile+" written to disk:\n")

    if fit_method == 4: # ellipse, slopes fit

        ibounded = 1 #=0 curve_fit (no guess), 1=leastsq, 2=bounded

        print("======== Fitting slopes =======")

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            popt, cov_x = curve_fit(func_ellipse_slopes, yp0, zp0, maxfev=10000)
        else:
            ishift = 0

            #dabam-4 (Amparo)
            p0 = 98.00
            q0 = 0.0775
            theta0 = 3.9e-3

            # # # #
            # #dabam-6 (Soleil) p=499.14 mm q= 4500 mm teta = 34.99 mrad
            # p0 = 499.14e-3
            # q0 = 4500e-3
            # theta0 = 34.99e-3
            # ishift = 1
            # #
            # #
            # # #
            # #dabam-19 #design parameter of ellipse: entrance arm: 420000mm; exit arm: 900mm; angle of incidence 3.052mrad
            # p0 = 420.0            #WRONG INPUTS?
            # q0 = 0.9              #WRONG INPUTS?
            # theta0 =  3.052e-3    #WRONG INPUTS?
            # # yp0 = yp0 - yp0[int(yp0.size/2)]
            #
            # #
            # #dabam-20 #design parameter of ellipse: entrance arm 9000mm; exit arm: 350mm; angle of incidence: 2.5deg
            # p0 = 9.0
            # q0 = 0.35
            # theta0 =  2.5*numpy.pi/180
            # #TODO:
            # yp0 = yp0 - yp0[int(yp0.size/2)]
            # zp0 = -zp0
            #
            # #
            # #dabam-21 #design parameter of ellipse: entrance arm: 7500mm; exit arm: 2500mm; angle of incidence 0.6deg
            # p0 = 7.5
            # q0 = 2.5
            # theta0 =  0.6*numpy.pi/180
            # ishift = 1

            p_guess = [p0,q0,theta0]
            zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2])

            if ishift:
                zp0 = zp0 + (zp1[0]-zp0[0])

            print("p0,q0,theta: ",p0,q0,theta0)

            fitfunc_ell_slopes = lambda p, x:   func_ellipse_slopes(x, p[0], p[1], p[2])
            errfunc_ell_slopes = lambda p, x, y: fitfunc_ell_slopes(p, x) - y

            if ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_slopes, p_guess, args=(yp0, zp0),
                                                          full_output=True)
            elif ibounded == 2:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [ (p0*0.998,p0*1.002) , (q0*0.8,q0*1.2), (theta0*0.98,theta0*1.02)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_slopes, p_guess, args=(yp0,zp0),
                                                            bounds=bounds,full_output=True)


            print("cov_x:", cov_x)
            # print("infodic['nfev']:", infodic['nfev'])
            # print("infodic['fvec']:", infodic['fvec'])
            # print("infodic['fjac']:", infodic['fjac'])
            # print("infodic['ipvt']:", infodic['ipvt'])
            # print("infodic['qtf']:", infodic['qtf'])
            # print("mesg:", mesg)
            # print("ier:", ier)

            print(">>>>> p_guess:", p_guess)
            #zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2])
            dd=numpy.concatenate( (yp0, zp1) ,axis=0).reshape(2,-1).transpose()
            outFile = "tmp_zp1.dat"
            numpy.savetxt(outFile,dd)
            print ("File "+outFile+" written to disk:\n")



        print(">>>>> popt (p,q,theta): ",popt)
        zp2 = func_ellipse_slopes(yp0, popt[0], popt[1], popt[2])
        #amparo  zp2 = func_ellipse_slopes(yp, 98.0, 82.0424e-3, 3.8754e-3, 0.0)

        if ibounded != 0: print ('Slope error RMS zp0-zp1:             %.3f urad'%(1e6*(zp0-zp1).std()))
        print ('Slope error RMS zp0-zp2:             %.3f urad'%(1e6*(zp0-zp2).std()))
        dd=numpy.concatenate( (yp0, zp2) ,axis=0).reshape(2,-1).transpose()
        outFile = "tmp_zp2.dat"
        numpy.savetxt(outFile,dd)
        print ("File "+outFile+" written to disk:\n")

    if fit_method == 5: # ellipse fitting heights using Xianbo method

        ibounded = 2 #=0 curve_fit (no guess), 1=leastsq, 2=bounded

        print("======== Fitting heights =======")

        if ibounded == 0:
            print("======== Curve fitting without guess =======")
            popt, cov_x = curve_fit(func_ellipse_xianbo, y0, z0, maxfev=10000)
        else:
            #dabam-4 (Amparo)
            # p0 = 98.00
            # q0 = 0.0775
            # theta0 = 3.9e-3
            # OFFSET = 0.0
            # XC = 0.0
            # #
            # #dabam-6 (Soleil) p=499.14 mm q= 4500 mm teta = 34.99 mrad
            # p0 = 499.14e-3
            # q0 = 4500e-3
            # theta0 = 34.99e-3
            # OFFSET = 0.0
            # XC = 0.0
            # #
            # #dabam-19 #design parameter of ellipse: entrance arm: 420000mm; exit arm: 900mm; angle of incidence 3.052mrad
            # p0 = 420.0
            # q0 = 0.9
            # theta0 =  3.052e-3
            # OFFSET = 0.0
            # XC = 0.0
            # #
            # #dabam-20 #design parameter of ellipse: entrance arm 9000mm; exit arm: 350mm; angle of incidence: 2.5deg
            p0 = 9.0
            q0 = 0.35
            theta0 =  2.5*numpy.pi/180
            OFFSET = 0.0
            XC = 75e-3
            # #TODO:
            # zp0 = -zp0
            # #
            # #dabam-21 #design parameter of ellipse: entrance arm: 7500mm; exit arm: 2500mm; angle of incidence 0.6deg
            # p0 = 7.5
            # q0 = 2.5
            # theta0 =  0.6*numpy.pi/180
            # OFFSET = 0.0
            # XC = 0.0

            p_guess = [p0,q0,theta0, OFFSET, XC]
            z1 = func_ellipse_xianbo(yp0, p_guess[0], p_guess[1], p_guess[2], p_guess[3], p_guess[4])

            # ishift = 0
            # if ishift:
            #     print(">>>>>>>> slope zp0[0], zp1[0], diff: ",zp0[0],zp1[1],zp0[0]-zp1[1])
            #     print(">>>>>>>>>>>>>>>>>>> shift value: ",(zp0-zp1)[1])
            #     p_guess[3]  = (zp0-zp1)[1]
            #     zp1 = func_ellipse(yp0, p_guess[0], p_guess[1], p_guess[2], p_guess[3])

            print("p0,q0,theta,OFFSET,XC: ",p0,q0,theta0,OFFSET,XC)

            fitfunc_ell_heights = lambda p, x: func_ellipse_xianbo(x, p[0], p[1], p[2], p[3], p[4])
            errfunc_ell_heights = lambda p, x, y: fitfunc_ell_heights(p, x) - y

            if ibounded == 1:
                print("======== Least Squares fitting =======")
                popt, cov_x, infodic, mesg, ier = leastsq(errfunc_ell_heights, p_guess, args=(y0, z0),
                                                          full_output=True)
            else:
                print("======== Bounded Least Squares fitting =======")
                # https://github.com/jjhelmus/leastsqbound-scipy
                from leastsqbound import leastsqbound
                bounds = [ (p0*0.998,p0*1.002) , (q0*0.8,q0*1.2), (theta0*0.98,theta0*1.02),
                           (OFFSET*0.9,OFFSET*1.2), (XC*0.9,XC*1.2)]
                popt, cov_x, infodic, mesg, ier = leastsqbound(errfunc_ell_heights, p_guess, args=(y0,z0),
                                                            bounds=bounds,full_output=True)


            print("cov_x:", cov_x)
            # print("infodic['nfev']:", infodic['nfev'])
            # print("infodic['fvec']:", infodic['fvec'])
            # print("infodic['fjac']:", infodic['fjac'])
            # print("infodic['ipvt']:", infodic['ipvt'])
            # print("infodic['qtf']:", infodic['qtf'])
            # print("mesg:", mesg)
            # print("ier:", ier)

            print(">>>>> p_guess:", p_guess)
            #zp1 = func_ellipse_slopes(yp0, p_guess[0], p_guess[1], p_guess[2], 0.0 ) #p_guess[3]) #TODO!!
            dd=numpy.concatenate( (y0, z1) ,axis=0).reshape(2,-1).transpose()
            outFile = "tmp_z1.dat"
            numpy.savetxt(outFile,dd)
            print ("File "+outFile+" written to disk:\n")



        print(">>>>> popt (p,q,theta): ",popt)

        z2 = func_ellipse_xianbo(y0, popt[0], popt[1], popt[2], popt[3], popt[4])
        #amparo z2 = func_ellipse(y0, 98.0, 81.826e-3, 3.865*1e-3)
        if ibounded != 0: print ('Height error RMS z0-z1:             %.3f nm'%(1e9*(z0-z1).std()))
        print ('height error RMS z0-z2:             %.3f nm'%(1e9*(z0-z2).std()))
        dd=numpy.concatenate( (y0, z2) ,axis=0).reshape(2,-1).transpose()
        outFile = "tmp_z2.dat"
        numpy.savetxt(outFile,dd)
        print ("File "+outFile+" written to disk:\n")

    #
    #plots
    #
    do_plots = 1
    if do_plots:
        #
        #plots
        #
        from matplotlib import pylab as plt

        if fit_method == 4: #slopes
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(yp0*1e3,zp0*1e6)
            if ibounded != 0: plt.plot(yp0*1e3,zp1*1e6)
            plt.plot(yp0*1e3,zp2*1e6)
            plt.title("slopes data (blue), starting (green) and optimized (red) ellipse")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(yp0*1e3,(zp0-zp2)*1e6)
            plt.title("residual slopes")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [urad]")
        elif (fit_method == 3 or fit_method == 5): #heights
            f1 = plt.figure(1)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0*1e3,z0*1e6)
            if ibounded != 0: plt.plot(y0*1e3,z1*1e6)
            plt.plot(y0*1e3,z2*1e6)
            plt.title("height data (blue), starting (green) and optimized (red) ellipse")
            plt.xlabel("Y [mm]")
            plt.ylabel("Zp [um]")

            f2 = plt.figure(2)
            ax = plt.gca()
            ax.get_xaxis().get_major_formatter().set_useOffset(False)
            ax.get_yaxis().get_major_formatter().set_useOffset(False)
            plt.plot(y0*1e3,(z0-z2)*1e9)
            plt.title("residual heights")
            plt.xlabel("Y [mm]")
            plt.ylabel("Z [nm]")



        plt.show()