コード例 #1
0
def sourceAlignment(dx, dy, dz):
    """
    Set up a trace of rays from the fiber source to
    the OAP. Determine wavefront error of collimated
    beam.
    """
    #Source
    rays = sources.circularbeam(125. / 4, 10000)
    tran.pointTo(rays, dx, dy, -775. / 2 + dz, reverse=1)
    rays[0] = np.sqrt((rays[1] + dx)**2 + (rays[2] + dy)**2 +
                      (775. / 2 + dz)**2)
    pdb.set_trace()

    #Go to focus
    tran.transform(rays, 0, 0, 0, np.pi / 2, 0, 0)
    tran.transform(rays, 0, -775. / 2, -775. / 2, 0, 0, 0)

    #Trace to parabola
    surf.conic(rays, 775., -1., nr=1.)
    tran.reflect(rays)

    #Restrict to 5" diameter
    ##    ind = np.logical_and(rays[3]>387.5-62.5,rays[3]<387.5+62.5)
    ##    tran.vignette(rays,ind=ind)

    #Reflect
    ##    for i in range(7,10):
    ##        rays[i] = -rays[i]
    tran.transform(rays, 0, 0, 775. / 2, 0, 0, 0)
    surf.flat(rays, nr=1.)

    pdb.set_trace()

    #Get OPD
    opd, dx0, dy0 = anal.interpolateVec(rays, 0, 200, 200)
    opd = man.remove2DLeg(opd, xo=1, yo=0)
    opd = man.remove2DLeg(opd, xo=0, yo=1)
    pv = ana.ptov(opd)

    plt.figure('OPD')
    plt.imshow(opd)
    plt.colorbar()

    wavesl = np.gradient(opd, dx0)
    resy = fit.legendre2d(wavesl[0], xo=2, yo=2)
    resx = fit.legendre2d(wavesl[1], xo=2, yo=2)
    resy[0][np.isnan(opd)] = np.nan
    resx[0][np.isnan(opd)] = np.nan

    plt.figure('Y')
    plt.imshow(resy[0] * 180 / np.pi * 60**2)
    plt.colorbar()

    plt.figure('X')
    plt.imshow(resx[0] * 180 / np.pi * 60**2)
    plt.colorbar()

    return pv * 1e6
コード例 #2
0
def fitTip(d):
    """
    Fit the tip term (roll) using the 1st and
    2,1 coefficients
    """
    res, c = fit.legendre2d(d, xo=1, yo=2, xl=[1, 0, 1, 1], yl=[0, 0, 0, 2])
    return ptov(d), ptov(d - res), c[0, 1], c[2, 1], res
コード例 #3
0
def fitTilt(d):
    """
    Fit the tilt term (pitch) using the 1st and 3rd
    order coefficients
    """
    res, c = fit.legendre2d(d, xo=0, yo=3, xl=[1, 0, 0, 0], yl=[0, 0, 1, 3])
    return ptov(d), ptov(d - res), c[1, 0], c[3, 0], res
コード例 #4
0
def remove2DLeg(din, xo=2, yo=0):
    """
    Remove a 2D Legendre fit to din up to
    xo and yo.
    """
    f = legendre2d(din, xo=xo, yo=yo)[0]

    return din - f
コード例 #5
0
def OPDtoLegendre(x, y, opd, xo, yo, xwidth=1., ywidth=1.):
    """
    Fit Legendre coefficients over ray XY plane to OPD.
    """
    #Perform Legendre fitting
    res = fit.legendre2d(opd, x=x / xwidth, y=y / ywidth, xo=xo, yo=yo)
    #Construct order arrays
    coeff = res[1]
    [xorder, yorder] = np.meshgrid(range(xo + 1), range(yo + 1))
    return coeff, xorder, yorder
コード例 #6
0
def fitTwist(d):
    """
    Fit the twist term (yaw) using the 1,1 and
    3,1 terms
    """
    res, c = fit.legendre2d(d,
                            xo=1,
                            yo=2,
                            xl=[1, 0, 1, 1, 1],
                            yl=[0, 0, 0, 1, 3])
    return ptov(d), ptov(d - res), c[1, 1], c[3, 1], res
コード例 #7
0
def fitFocus(d):
    """
    Fit up to 4th order for focus and return the
    2nd and 4th order coefficients
    """
    res, c = fit.legendre2d(d,
                            xo=0,
                            yo=4,
                            xl=[1, 0, 0, 0, 0],
                            yl=[1, 0, 1, 2, 4])
    return ptov(d), ptov(d - res), c[2, 0], c[4, 0], res
コード例 #8
0
def fom_sl(tdata, x=None, y=None):
    """Fit slope of surface after plane level"""
    """This was taking a second argument dy, changed 2019/03/28 to data,x,y,
    do a workaround to keep old compatibility."""
    #tdata=tdata[ci0:ci1,ci0:ci1]

    if y is None and x is not None:
        dy = x
    else:
        dy = np.diff(diff.y)[0]
    tdata = tdata - fit.legendre2d(tdata, 1, 1)[0]
    grad = np.gradient(tdata)
    slopeax = grad[0][:-1, :] / 1000. * 206265 / dy  #in arcseconds from um
    return np.nanstd(slopeax)
コード例 #9
0
def OPDtoLegendreP(x, y, opd, xo, yo, xwidth=1., ywidth=1.):
    """
    Fit Legendre coefficients over ray XY plane to OPD.
    Return the derivatives in both axes
    """
    #Perform Legendre fitting
    res = fit.legendre2d(opd, x=x / xwidth, y=y / ywidth, xo=xo, yo=yo)
    #Construct order arrays
    coeff = res[1]
    [xorder, yorder] = np.meshgrid(range(xo + 1), range(yo + 1))
    #Construct the derivatives using the special function module
    cx = np.polynomial.legendre.legder(res[1], axis=0)
    cy = np.polynomial.legendre.legder(res[1], axis=1)
    #gy = np.polynomial.legendre.legval2d(x/xwidth,y/ywidth,cx)/xwidth
    #gx = np.polynomial.legendre.legval2d(x/xwidth,y/ywidth,cy)/ywidth
    gy = np.polynomial.legendre.legval2d(-y / ywidth, x / xwidth, cx) / ywidth
    gx = np.polynomial.legendre.legval2d(-y / ywidth, x / xwidth, cy) / xwidth

    return coeff, xorder, yorder, gx, gy
コード例 #10
0
def findDistortionCoefficients(filename, Nx, Ny, method='cubic'):
    """
    Fit L-L coefficients to distortion data produced by Vanessa.
    """
    #Load in data
    d = np.transpose(np.genfromtxt(filename, skip_header=1, delimiter=','))

    #Compute angle and radial perturbations
    x0, y0, z0 = d[2:5]
    t0 = np.arctan2(x0, -z0)
    r0 = 1 - np.sqrt(x0**2 + z0**2)

    #Define regular grid
    tg,zg = np.meshgrid(np.linspace(t0.min(),t0.max(),Nx+2),\
                        np.linspace(y0.min(),y0.max(),Ny+2))

    #Regrid nominal node positions
    d0 = griddata((t0, y0), r0, (tg, zg), method=method)

    #Find perturbed node positions
    x1, y1, z1 = x0 + d[5], y0 + d[6], z0 + d[7]
    t1 = np.arctan2(x1, -z1)
    r1 = 1 - np.sqrt(x1**2 + z1**2)
    #Regrid distorted nodes onto original grid
    d1 = griddata((t1, y1), r1, (tg, zg), method=method)

    #Get distortion data
    #
    d = d1 - d0

    #Apply fit
    res = fit.legendre2d(d, xo=10, yo=10)
    xo, yo = np.meshgrid(np.arange(11), np.arange(11))

    pdb.set_trace()

    #Return coefficients and order arrays
    return res[1].flatten(), xo.flatten(), yo.flatten()
コード例 #11
0
def calculatePSD2(wdata,xg,yg,outname="",wfun=None,vrange=[None,None],rmsrange=None,prange=None,fignum=1,misal_deg=(1,1),leg_deg=(10,10)):
    """Updated version with subtracted 4 terms legendre."""
    """given points w, calculate and plot surface maps with different leveling (piston, tilt, sag, 10 legendre)
    use psd2d to calculate and save x and y 2d PSDs, plots only y.
    fignum window where to plot, if fignnum is 0 current figure is cleared, if None new figure is created. Default to figure 1 ."""
    ##STILL AWFUL CODE
    # misal_deg is useless, since data are expected to be already leveled.
    # if not, still can be applied, but is quite useless.

    ###AWFUL CODE, partially fixed -> fix plotting window

    ## FOUR PANEL PLOT save as _lev.png, _piston.dat, _tilt.dat, _sag.dat
    ## on fignum
    fig=fignumber(fignum)
    plt.clf()
    figManager = plt.get_current_fig_manager()
    figManager.window.showMaximized()

    #
    wdata=-fit.legendre2d(wdata,1,1)[0]
    lwdata=wdata-fit.legendre2d(wdata,*misal_deg)[0]
    lwdata2=wdata-fit.legendre2d(wdata,*leg_deg)[0]
    #
    #make plots
    ax=compare_images([wdata,lwdata,lwdata2],xg,yg,titles=['original','cone corrected','10 legendre 2D corrected'],fignum=0,commonscale=True,vmin=vrange[0],vmax=vrange[1])  #generator of axis, not sure how it can work below, missing something?
    for im in ax:
        plt.xlabel('X (mm)')
        plt.ylabel('Y (mm)')
    #
    ##return wdata,lwdata,lwdata2

    wdata,lwdata,lwdata2=leveldata(wdata,xg,yg) #calculate and make a plot with 3 panels
    if outname:
        np.savetxt(fn_add_subfix(outname,'_piston','.dat'),wdata) #doesn't  write x and y
        np.savetxt(fn_add_subfix(outname,'_%2i_%2i_misal'%misal_deg,'.dat'),lwdata)
        np.savetxt(fn_add_subfix(outname,'_%2i_%2i_leg'%leg_deg,'.dat'),lwdata2)

    leg10=wdata-fit.legendre2d(wdata,*leg_deg)[0]
    #forth panel contains legendre
    plt.subplot(224)
    plt.imshow(leg10,extent=(xg[0],xg[-1],yg[0],yg[-1]),
                interpolation='None',aspect='auto')
    plt.title('(%i,%i) 2D legendre removed'%leg_deg)
    plt.colorbar()
    #display(plt.gcf())
    if outname:
        plt.savefig(fn_add_subfix(outname,'_lev','.png'))

    ## DATA OUTPUT save as _psd.dat, psd2d creates
    #create packed data for txt output
    #containing x and y psds, with 3 different levelings
    #resulting in 6 couples freq/psd.
    # matches the order specified in header

    #header for final matrix output, define labels of psd sequence
    head='yfreq ypsd xfreq xpsd ylevfreq ylevpsd xlevfreq xlevpsd ysagfreq ysagpsd xsagfreq xsagpsd'

    #this assumes x and y are same xg and yg on all datalist
    #change this part, we are no more interested in doing psd on all possible leveling, only 4 terms removed by line
    # along the direction of interest, however to keep constant number of columns, replace piston, tilt, sag
    # with tilt, sag, 4 legendre
    datalist=[wdata,lwdata,lwdata2]
    labels=['_tilt','_mis','_leg'] #postfix for output file
    flist=[]
    psdlist=[]
    for d,l in zip(datalist,labels):
        plt.figure(3)
        #x and y psds
        fx,px=psd2d(d.T,yg,xg,wfun=wfun) #psds along x, no plot
        fy,py=plot_psd2d(d,xg,yg,outname=fn_add_subfix(outname,l),wfun=wfun,
            rmsrange=rmsrange,prange=prange,vrange=vrange) #psds along y, plot
        #display(plt.gcf())

        #note y goes first
        flist.extend([fy,fx])
        psdlist.extend([py,px])
    avgpsdlist=[avgpsd2d(p) for p in psdlist]

    #generate output array and save it with header
    outarr=np.empty((np.max([len(f) for f in flist]),len(psdlist)*2))*np.nan
    for i,(f,p) in enumerate(zip(flist,avgpsdlist)):
        outarr[:len(f),i*2]=f
        outarr[:len(p),i*2+1]=p

    if outname:
        np.savetxt(fn_add_subfix(outname,'_psd','.dat'),outarr,header=head,fmt='%f')

    ## PLOT AVG PSDs save as _psds.png
    fw1,fw1m,fw2,fw2m,fw3,fw3m=flist  #used only in plot
    pw1avg,pw1mavg,pw2avg,pw2mavg,pw3avg,pw3mavg=avgpsdlist  #average psds
    plt.figure(2)
    plt.clf()
    plt.plot(fw1,pw1avg,label='Y')
    plt.plot(fw2,pw2avg,label='Y lev.')
    plt.plot(fw3,pw3avg,label='Y sag.')
    plt.plot(fw1m,pw1mavg,'--',label='X')
    plt.plot(fw2m,pw2mavg,'--',label='X lev.')
    plt.plot(fw3m,pw3mavg,'--',label='X sag.')
    plt.loglog()
    plt.grid()
    plt.legend(loc=0)
    if outname:
        plt.savefig(fn_add_subfix(outname,'_psds','.png'))

    return outarr
コード例 #12
0
def calculatePSD(wdata,xg,yg,outname="",wfun=None,vrange=None,rmsrange=None,prange=None,fignum=1):
    """given points w, calculate and plot surface maps with different leveling (piston, tilt, sag, 10 legendre)
    use psd2d to calculate and save x and y 2d PSDs, plots only y.
    fignum window where to plot, if fignnum is 0 current figure is cleared, if None new figure is created. Default to figure 1 ."""
    ###AWFUL CODE, partially fixed -> fix plotting window

    ## FOUR PANEL PLOT save as _lev.png, _piston.dat, _tilt.dat, _sag.dat
    ## on fignum
    if fignum==0:
        plt.clf()
    else:
        plt.figure(fignum)
    plt.clf()
    figManager = plt.get_current_fig_manager()
    figManager.window.showMaximized()
    #xg,yg=points_find_grid(w,'grid')[1]
    wdata,lwdata,lwdata2=leveldata(wdata,xg,yg) #calculate and make a plot with 3 panels
    if outname:
        np.savetxt(fn_add_subfix(outname,'_piston','.dat'),wdata) #doesn't  write x and y
        np.savetxt(fn_add_subfix(outname,'_tilt','.dat'),lwdata)
        np.savetxt(fn_add_subfix(outname,'_sag','.dat'),lwdata2)

    leg10=wdata-fit.legendre2d(wdata,10,10)[0]
    #forth panel contains legendre
    plt.subplot(224)
    plt.imshow(leg10,extent=(xg[0],xg[-1],yg[0],yg[-1]),
                interpolation='None',aspect='auto')
    plt.title('10 legendre')
    plt.colorbar()
    #display(plt.gcf())
    if outname:
        plt.savefig(fn_add_subfix(outname,'_lev','.png'))

    ## DATA OUTPUT save as _psd.dat, psd2d creates
    #create packed data for txt output
    #containing x and y psds, with 3 different levelings
    #resulting in 6 couples freq/psd.
    # matches the order specified in header

    #header for final matrix output, define labels of psd sequence
    head='yfreq ypsd xfreq xpsd ylevfreq ylevpsd xlevfreq xlevpsd ysagfreq ysagpsd xsagfreq xsagpsd'

    #this assumes x and y are same xg and yg on all datalist
    datalist=[wdata,lwdata,lwdata2]
    labels=['_piston','_tilt','_sag'] #postfix for output file
    flist=[]
    psdlist=[]
    for d,l in zip(datalist,labels):
        plt.figure(3)
        #x and y psds
        fx,px=psd2d(d.T,yg,xg,wfun=wfun) #psds along x, no plot
        fy,py=plot_psd2d(d,xg,yg,outname=fn_add_subfix(outname,l),wfun=wfun,
            rmsrange=rmsrange,prange=prange,vrange=vrange) #psds along y, plot
        #display(plt.gcf())

        #note y goes first
        flist.extend([fy,fx])
        psdlist.extend([py,px])
    avgpsdlist=[avgpsd2d(p) for p in psdlist]

    #generate output array and save it with header
    outarr=np.empty((np.max([len(f) for f in flist]),len(psdlist)*2))*np.nan
    for i,(f,p) in enumerate(zip(flist,avgpsdlist)):
        outarr[:len(f),i*2]=f
        outarr[:len(p),i*2+1]=p

    if outname:
        np.savetxt(fn_add_subfix(outname,'_psd','.dat'),outarr,header=head,fmt='%f')

    ## PLOT AVG PSDs save as _psds.png
    fw1,fw1m,fw2,fw2m,fw3,fw3m=flist  #used only in plot
    pw1avg,pw1mavg,pw2avg,pw2mavg,pw3avg,pw3mavg=avgpsdlist  #average psds
    plt.figure(2)
    plt.clf()
    plt.plot(fw1,pw1avg,label='Y')
    plt.plot(fw2,pw2avg,label='Y lev.')
    plt.plot(fw3,pw3avg,label='Y sag.')
    plt.plot(fw1m,pw1mavg,'--',label='X')
    plt.plot(fw2m,pw2mavg,'--',label='X lev.')
    plt.plot(fw3m,pw3mavg,'--',label='X sag.')
    plt.loglog()
    plt.grid()
    plt.legend(loc=0)
    if outname:
        plt.savefig(fn_add_subfix(outname,'_psds','.png'))

    return outarr
コード例 #13
0
def plot_surface_analysis(wdata,x,y,label="",outfolder=None,nsigma_crange=1,fignum=None,
    figsize=(9.6,6.7),psdrange=None,levelingfunc=None,frange=None):
    """Create two panel preview plots for data. 
    
    This is two panels of raw and filtered data (second order removed) + histogram 
       of height distribution + PSD. 
    Label is typically the filename and is used to generate title and output filenames.
    fignum and figsize are for PSD2D figure (fignum=0 clear and reuse current figure, 
    None create new).
    nsigma_crange and levelingfunc are used to evaluate color range for plot by iteratively 
    leveling and removing outliers at nsigma until a convergence is reached.
    psdrange is used 
    frange is used for plot of PSD2D
    """
    from pySurf.psd2d import psd2d_analysis
    
    units=['mm','mm','$\mu$m']
    order_remove=2 #remove sag, this is the order that is removed in leveled panel
    if np.size(units)==1:   #unneded, put here just in case I decide to take units
        units=np.repeat(units,3)  #as argument. However ideally should be put in plot psd function.
    
    if levelingfunc is None:
        levelingfunc=lambda x: x-legendre2d(x,1,1)[0]
    
    if outfolder is not None:
        os.makedirs(os.path.join(outfolder,'PSD2D'),exist_ok=True)
    else:
        print('OUTFOLDER is none')
    
    wdata=levelingfunc(wdata)  #added 20181101
    
    rms=np.nanstd(wdata)
    #crange=remove_outliers(wdata,nsigma=nsigma_crange,itmax=1,range=True)
    crange=remove_outliers(wdata,nsigma=nsigma_crange,
        flattening_func=levelingfunc,itmax=2,span=1)
    
    plt.clf()
    
    #FULL DATA
    plt.subplot(221)
    #plt.subplot2grid((2,2),(0,0),1,1)
    plot_data(wdata,x,y,units=units,title='leveled data',stats=True)
    plt.clim(*crange)
    
    #SUBTRACT LEGENDRE
    ldata=levellegendre(y,wdata,order_remove)
    plt.subplot(223)
    lrange=remove_outliers(ldata,nsigma=nsigma_crange,itmax=1,span=True)
    #plt.subplot2grid((2,2),(1,0),1,1)
    plot_data(ldata,x,y,units=units,title='%i orders legendre removed'%order_remove,stats=True)
    plt.clim(*lrange) 
    
    #HISTOGRAM
    #plt.subplot2grid((2,2),(0,1),2,1)
    plt.subplot(222)
    plt.hist(wdata.flatten()[np.isfinite(wdata.flatten())],bins=100,label='full data')
    plt.hist(ldata.flatten()[np.isfinite(ldata.flatten())],bins=100,color='r',alpha=0.2,label='%i orders filtered'%order_remove)
    #plt.vlines(crange,*plt.ylim())
    plt.vlines(crange,*plt.ylim(),label='plot range raw',linestyle='-.')
    plt.vlines(lrange,*plt.ylim(),label='plot range lev',linestyle=':')
    plt.legend(loc=0)
    
    #FREQUENCY AND PSD ANALYSIS
    if fignum==0:   #this is the figure created by psd2d_analysis
        plt.clf()
        fig = plt.gcf()
    #pdb.set_trace()
    stax=plt.gca()   #preserve current axis
    f,p=psd2d_analysis(ldata,x,y,title=label,
        wfun=np.hanning,fignum=fignum,vrange=lrange,
        prange=psdrange,units=units,
        rmsrange=frange)#,ax2f=[0,1,0,0])
    plt.ylabel('slice rms ($\mu$m)')
    ps=projection(p,axis=1,span=True) #avgpsd2d(p,span=1)      
    if outfolder:
        maximize()
        plt.savefig(os.path.join(outfolder,'PSD2D',
            fn_add_subfix(label,"_psd2d",'.png')))
        save_data(os.path.join(outfolder,'PSD2D',fn_add_subfix(label,"_psd2d",'.txt')),
            p,x,f)
        np.savetxt(os.path.join(outfolder,fn_add_subfix(label,"_psd",'.txt')),np.vstack([f,ps[0],ps[1],ps[2]]).T,
            header='f(%s^-1)\tPSD(%s^2%s)AVG\tmin\tmax'%(units[1],units[2],units[1]),fmt='%f')
            #pdb.set_trace()
    plt.sca(stax)
    
    plt.subplot(224)
    plt.ylabel('axial PSD ('+units[2]+'$^2$ '+units[1]+')')
    plt.xlabel('Freq. ('+units[1]+'$^{-1}$)')
    plt.plot(f,ps[0],label='AVG')
    plt.plot(f,ps[1],label='point-wise min')
    plt.plot(f,ps[2],label='point-wise max')
    plt.plot(f,p[:,p.shape[1]//2],label='central profile')
    plt.ylim(psdrange)
    plt.loglog()
    plt.grid(1)
    plt.legend(loc=0) 
    #ideally to be replaced by:
    """
    plt.subplot(224)
    plot_psd(((f,ps[0]),(f,ps[1]),(f,ps[2),(f,p[:,p.shape[1]//2])),
            ['AVG','point-wise min','point-wise max','central profile'])
    plt.ylabel('axial '+plt.ylabel)
    plt.ylim(psdrange)
    """

    plt.suptitle('%s: rms=%5.3f 10$^{-3}$'%(label,rms*1000)+units[2])
    plt.tight_layout(rect=[0, 0.03, 1, 0.95])
    
    if outfolder:
        plt.savefig(os.path.join(outfolder,fn_add_subfix(label,"",'.png')))
    
    return (ldata,x,y),(f,p)