Пример #1
0
def test_with_image(infile, outfolder=None):
    """apply a scale on a image. Image can be aligned and zoomed to verify scale
    and scale update."""

    infolder = os.path.dirname(infile)
    imgfile = os.path.basename(infile)
    img = plt.imread(infile)

    #plot green channel
    plt.clf()
    plt.imshow(img[:, :, 1])

    #fix pixsize: 300 um is 810 units of axis (pixels).
    #visible is set, scale should be immediately plotted.
    s = Scale(
        300 / 810., 'um', True
    )  #810 pixel for 30 small ruler units, each unit is 10 um. pixsize is 300/810.

    if outfolder is not None:
        plt.savefig(
            os.path.join(outfolder, fn_add_subfix(imgfile, '_01', '.png')))

    #zoom 2x
    plt.xlim(np.array(plt.xlim()) // 2)
    plt.ylim(np.array(plt.ylim()) // 2)
    s.draw()
    if outfolder is not None:
        plt.savefig(
            os.path.join(outfolder, fn_add_subfix(imgfile, '_02', '.png')))
    return s
Пример #2
0
def subtract_cone(pp, odr, sampleName='', outfile=None, vmin=None, vmax=None):
    #not used in v1
    """
    odr: 6-vector (origin_y,origin_y,origin_z,direction_x,direction_y,direction_z),
        note that  this is redundant, since only two components are enough for direction 
        (magnitude is irrelevant).
    pp: complete set of points Npx3
    """
    fom, deltaR, coeff = cone_error(odr, pp, retall=True)
    xymin = np.nanmin(pp, axis=0)[0:2]
    xymax = np.nanmax(pp, axis=0)[0:2]
    rp = plot_points(
        np.hstack([pp[:, 0:2], deltaR[:, None] * 1000]),
        shape=(281, 3001))  #this is done to easily replot and change scale

    #surface map and data
    plt.clf()
    plt.imshow(rp,
               aspect='equal',
               interpolation='none',
               vmin=vmin,
               vmax=vmax,
               extent=[xymin[1], xymax[1], xymin[0], xymax[0]])
    plt.colorbar()
    plt.title(((sampleName + ' - ') if sampleName else ('')) +
              'best-fit-cone removed.')
    plt.xlabel('Y(mm)')
    plt.ylabel('X(mm)')
    if outfile:
        plt.savefig(fn_add_subfix(outfile, '_cone', 'png'))
        save_points(np.hstack([pp[:, 0:2], deltaR[:, None] * 1000]),
                    fn_add_subfix(outfile, '_cone'))

    #cone output
    m = coeff[0]
    print('Cone angle:%s+/-%s rad(%s+/-%s deg) ' %
          (np.arctan(m), 0, np.arctan(m) * 180 / np.pi, 0))
    print('Axis intercept at x=0: %smm ' % (coeff[1]))
    misal = (np.arccos(1 / np.sqrt(1 + ((odr[2:]**2).sum()))))
    print('Misalignment of optical axis: %s rad (%s deg)' %
          (misal, misal * 180. / pi))

    #rms output
    print('rms entire surface %s' % (np.nanstd))
    plt.figure()
    plt.plot(np.nanstd(rp))
    plt.plot(np.nanstd(rp, axis=0))
    plt.plot(np.nanstd(rp, axis=1))

    #mask outliers on a copy
    rp2 = rp[:]
    np.where(np.isnan(rp2))
    return fom, deltaR, coeff
Пример #3
0
def subtract_cylinder(pp, odr, sampleName=''):
    #not used in v1
    """
    odr: 6-vector (origin_y,origin_y,origin_z,direction_x,direction_y,direction_z),
        note that  this is redundant, since only two components are enough for direction 
        (magnitude is irrelevant).
    pp: complete set of points Npx3
    """
    fom, deltaR, radius = cylinder_error(odr, pp, retall=False, extra=True)
    xymin = np.nanmin(pp, axis=0)[0:2]
    xymax = np.nanmax(pp, axis=0)[0:2]
    rp = plot_points(
        np.hstack([pp[:, 0:2], deltaR[:, None] * 1000]),
        shape=(281, 3001))  #this is done to easily replot and change scale

    #surface map and data
    plt.clf()
    plt.imshow(rp,
               aspect='equal',
               interpolation='none',
               vmin=-5,
               vmax=10,
               extent=[xymin[1], xymax[1], xymin[0], xymax[0]])
    plt.colorbar()
    plt.title(sampleName + (sampleName if sampleName else '') +
              'best-fit-cylinder removed.')
    plt.xlabel('Y(mm)')
    plt.ylabel('X(mm)')
    plt.savefig(fn_add_subfix(datafile, '_cylinder', 'png'))
    save_points(np.hstack([pp[:, 0:2], deltaR[:, None] * 1000]),
                fn_add_subfix(datafile, '_cylinder'))

    #cylinder output
    print('Best fit radius %s' % radius)
    misal = np.arccos(1 / np.sqrt(1 + ((odr[2:]**2).sum())))
    print('Misalignment of optical axis: %s rad (%s deg)' %
          (misal, misal * np.pi / 180))

    #rms output
    print('rms entire surface %s' % (np.nanstd(rp)))
    plt.figure()
    plt.plot(np.nanstd(rp))
    plt.plot(np.nanstd(rp, axis=0))
    plt.plot(np.nanstd(rp, axis=1))

    #mask outliers on a copy
    rp2 = rp[:]
    np.where(np.isnan(rp2))
Пример #4
0
def test_reader(file, reader, outfolder=None, infolder=None, **kwargs):
    """called without `raw` flag, return data,x,y. Infolder is taken from file or can be passed (e.g. to point to local test data)."""

    import os
    import matplotlib.pyplot as plt
    from pySurf.data2D import plot_data

    if infolder is None:
        infolder = os.path.dirname(file)

    df = os.path.join(infolder, os.path.basename(file))
    res = reader(df, **kwargs)
    header = reader(df, header=True, **kwargs)
    print("reading file %s with reader %s" % (df, reader))
    print("returned values", [r.shape for r in res], header)

    plot_data(res[0], res[1], res[2])
    plt.title(
        os.path.basename(file) + ' ' +
        ' '.join(["%s=%s" % (k, v) for k, v in kwargs.items()]))
    if outfolder is not None:
        if outfolder == "":
            display(plt.gcf())
        else:
            outname = os.path.join(infolder, outfolder, os.path.basename(df))
            os.makedirs(os.path.dirname(outname), exist_ok=True)
            plt.savefig(fn_add_subfix(outname, '', '.png'))
    return res, header
Пример #5
0
def test_slicerms():
    """test plot options for slicerms """
    wf=r'test\PSD\2dpsd\171010_Secondary_Mandrel_C3_RefSub.dat'
    outfolder=r'test\PSD\2dpsd\output'
    wdata,x,y=get_data(wf,matrix=True,addaxis=True)
    outfile=fn_add_subfix(wf,'_4leg',strip=True,pre=outfolder+os.path.sep)

    f3,psd3=psd2d(levellegendre(y,wdata,4),x,y,wfun=np.hanning,norm=1,rmsnorm=True)
    plt.figure()
    r=plot_rms_power(f3,psd3,x=None,rmsrange=None)
    plt.savefig(fn_add_subfix(outfile,'_testslicerms_01','.png'))
    plt.figure()
    plot_rms_power(f3,psd3,x=x,rmsrange=[0.1,1])
    plt.savefig(fn_add_subfix(outfile,'_testslicerms_02','.png'))
    plt.figure()
    plot_rms_power(f3,psd3,x=x,rmsrange=[0.1,1],ax2f=[1])
    plt.savefig(fn_add_subfix(outfile,'_testslicerms_03','.png'))
    plt.figure()
    plot_rms_power(f3,psd3,x=x,rmsrange=[[None,0.1],[0.1,1],[1,None]],ax2f=[0,1,1])
    plt.savefig(fn_add_subfix(outfile,'_testslicerms_04','.png'))
Пример #6
0
def plot_diffs(dataset,repeatlist,labels=None,outfolder=None,nsigma_crange=1,fignum=None,figsize=(9.6,6.7)):
    """Generate comparison and difference plots for a list of datasets (data,x,y) and a list of indices
    `repeatlist` as (index1,index2,label). An optional list of `labels` matching data in repeatlist can be provided,
    and then are used for titles of plots, otherwise numeric indices are simply used."""

    stats=[]
    result=[]
    #plot surface map, who knows why on figure 5
    fignumber(fignum,figsize=figsize)
    for i1,i2,t in repeatlist:
        d1,d2=dataset[i1],dataset[i2]
        diff=d1[0]-d2[0]
        result.append((diff,d1[1],d1[2]))
        #mng = plt.get_current_fig_manager()
        #mng.window.showMaximized()
        plt.clf()
        ax1,ax2,ax3=diff_images(d1[0],d2[0],d2[1],d2[2],fignum=0)  #x and y are taken from second data
        if labels is not None:
            ax1.set_title(labels[i1])
            ax2.set_title(labels[i2])
            stats.append([labels[i1],labels[i2],np.nanstd(diff)])
        else:
            stats.append([i1,i2,np.nanstd(diff)])
        ax3.set_title('Diff, rms= %5.3f nm'%(np.nanstd(diff)*1000) )
        plt.sca(ax3)
        plt.clim(*filtered_span(diff,nsigma=nsigma_crange,itmax=1,span=True))
        ax1.set_aspect('equal')
        ax2.set_aspect('equal')
        ax3.set_aspect('equal')
        plt.suptitle(t)
        plt.tight_layout()
        if outfolder:
            #pdb.set_trace()
            plt.savefig(os.path.join(outfolder,fn_add_subfix("diff","_%i_%i"%(i1,i2),'.jpg')))
            save_data(os.path.join(outfolder,fn_add_subfix("diff","_%i_%i"%(i1,i2),'.dat')),
                diff,d1[1],d1[2])

    if outfolder:
        np.savetxt(os.path.join(outfolder,"diff_report.txt"),result,fmt="%s")

    return result
Пример #7
0
def plot_rep_diff(dlist,outfile=None,dis=True):
    """Get three 2d arrays in a list. Calculate rotating differences for different component
    removal: plane, cylinder, cone, legendre.
    returns an 4 element list with the 4 possible removal for the 3 combinations of files to diff  """

    res=[]    
    
    plt.close('all')
    plt.figure(1)
    res.append(dcouples_plot(dlist))
    plt.suptitle('Differences RAW')
    if outfile is not None:
        plt.savefig(fn_add_subfix(outfile,'_raw','.png',pre='raw\\diff_'))
    if dis: display(plt.gcf())    
    
    plt.figure(2)
    res.append(dcouples_plot([removemis(dd,fit.fitCylMisalign) for dd in dlist]))
    plt.suptitle('Differences CYL removed')
    if outfile is not None:
        plt.savefig(fn_add_subfix(outfile,'_cyl','.png',pre='cyl\\diff_'))
    if dis: display(plt.gcf())    

    plt.figure(3)
    res.append(dcouples_plot([removemis(dd,fit.fitConeMisalign) for dd in dlist]))
    plt.suptitle('Differences CONE removed')
    if outfile is not None:
        plt.savefig(fn_add_subfix(outfile,'_cone','.png',pre='cone\\diff_'))
    if dis: display(plt.gcf())    

    plt.figure(4)
    res.append(dcouples_plot([dd.level((2,2)) for dd in dlist]))
    plt.suptitle('Differences 2,2 Legendre removed')
    if outfile is not None:
        plt.savefig(fn_add_subfix(outfile,'_leg','.png',pre='leg\\diff_'))
    if dis: display(plt.gcf())    
    
    return res
Пример #8
0
    def psd(
        self,
        wfun=None,
        rmsnorm=True,
        norm=1,
        analysis=False,
        subfix="",
        name=None,
        *args,
        **kwargs
    ):
        """return a PSD2D object with 2D psd of self.
        If analysis is set True, psd2d_analysis plots are generated and related parameters
          are passed as args. You need to pass also title, it generates output,
          this is subject to change, at the moment, pass empty string to generate plots
          or string to create output graphics.
        subfix and name are used to control the name of returned object.
        units are set in units of self because of the ambiguity mentioned in
        pySurf.psd2d.psd_units, and consistently with functions in `pySurf.psd2d`.
        """

        if analysis:
            title = kwargs.pop("title", (name if name is not None else ""))
            f, p = psd2d_analysis(
                self.data,
                self.x,
                self.y,
                wfun=wfun,
                norm=norm,
                rmsnorm=rmsnorm,
                title=title,
                units=self.units,
                *args,
                **kwargs
            )
        else:
            f, p = psd2d(
                self.data,
                self.x,
                self.y,
                wfun=wfun,
                norm=norm,
                rmsnorm=rmsnorm,
                *args,
                **kwargs
            )

        newname = name if name is not None else fn_add_subfix(self.name, subfix)
        return PSD2D(p, self.x, f, units=self.units, name=newname)
Пример #9
0
def tomg_file(f):
    """convert matrix data file to 'smart' format martagiorgia.
    See format specs at the end.
    """
    p = get_points(f, delimiter=' ')
    dx, dy = points_find_grid(p, 'step')[1]
    pp = matrix_to_points2(points_autoresample(p)[0])
    pp = pp[pp[:, 0].argsort(kind='mergesort'), :] * [1, 1, 1000.]
    save_points(fn_add_subfix(f, '', '.mgf'),
                pp,
                fill_value='32767',
                header='\n'.join([str(dx), str(dy)]),
                newline='\n',
                delimiter='\n',
                comments='')
Пример #10
0
def test_plotpsd2d():
    """test of 3 panel psd2d plot, including 2d psd and slice rms. """
    prange=np.array((1e-10,1))#np.array((5e-8,1.e-5))  #color scale of 2d psd plot
    rmsrange=[[0.1,1],[0.01,0.1]]  #range of frequency for rms calculation
    vrange_surf=([-0.15,0.15])  #color scale of surface map
    vrange_leg=([-0.025,0.025])   #color scale of legendre removed map

    wf=r'test\PSD\2dpsd\171010_Secondary_Mandrel_C3_RefSub.dat'
    outfolder=r'test\PSD\2dpsd\output'
    wdata,x,y=get_data(wf,matrix=True,addaxis=True)
    outfile=fn_add_subfix(wf,'_4leg',strip=True,pre=outfolder+os.path.sep)

    plt.figure()
    #PSD with polynomial removal and average in f3, psd3 and wptot
    f3,psd3=plot_psd2d(levellegendre(y,wdata,2),x,y,wfun=np.hanning,
                outname=outfile,vrange=vrange_leg,prange=prange,rmsrange=rmsrange,ax2f=True)
Пример #11
0
def test_psd2d():
    """test of plotting 2dpsd alone """
    from pySurf.data2D import get_data, levellegendre

    rmsrange=[[None,0.1],[0.1,0.2],[0.2,1],[1,None]]  #list of frequency intervals for rms
    ax2f=[0,1,1,0,0]             #   axis where to plot rms corresponding to intervals in rmsrange: 1 right, 0 left
    wfun  = np.hanning           #   type of windows for fourier transform
    units = ("mm","mm","$\mu$m") #   units of surface data from which PSD is calculated

    vrange_surf=([-0.5,0.5])  #color scale of surface map
    vrange_leg=([-0.05,0.05])   #color scale of legendre removed map
    prange=np.array((1e-8,1.e-3))#np.array((5e-8,1.e-5))  #color scale of 2d psd plot
    order=2                     #highest legendre order to remove (2=sag)

    TEST_PATH=os.path.join(os.path.dirname(os.path.realpath(__file__)),r'test\PSD\2dpsd')
    wf=os.path.join(TEST_PATH,r'171010_Secondary_Mandrel_C3_RefSub.dat')
    OUTFOLDER=os.path.join(TEST_PATH,'output')
    OUTFILE=fn_add_subfix(wf,'_4leg',strip=True,pre=OUTFOLDER+os.path.sep)

    wdata,x,y=get_data(wf,matrix=True,addaxis=True)
    fs,ps=psd2d_analysis(levellegendre(y,wdata,order),x,y,outname=OUTFILE,wfun=np.hanning,
        rmsrange=rmsrange,prange=prange,ax2f=ax2f,units=units)

    f3,psd3=psd2d(levellegendre(y,wdata,order),x,y,wfun=np.hanning,norm=1,rmsnorm=True)

    plt.figure(1)
    plt.clf()
    plot_psd2d(f3,psd3,x,rmsrange=rmsrange)
    plt.figure(2)
    plt.clf()
    plot_psd2d(f3,psd3,x,rmsrange=rmsrange,prange=prange)

    """
    plt.figure()
    plt.title('2D PSD')
    plt.imshow(psd3,norm=LogNorm(),interpolation='none',
        extent=(x[0],x[-1],f3[0],f3[-1]),origin='lower',aspect='auto')
    plt.colorbar()
    """

    plt.figure(3)
    plt.clf()
    plt.title('2D PSD')
    plt.imshow(psd3,norm=LogNorm(vmin=prange[0],vmax=prange[1]),interpolation='none',
        extent=(x[0],x[-1],f3[0],f3[-1]),origin='lower',aspect='auto')
    plt.colorbar()
Пример #12
0
def test_class_init(wfile=None, *args, **kwargs):
    """test init and plot"""
    from pathlib import PureWindowsPath

    from dataIO.fn_add_subfix import fn_add_subfix
    
    from pySurf.data2D import load_test_data

    # from pySurf.data2D import data, load_test

    d1, x1, y1 = load_test_data(wfile, *args, **kwargs)

    plt.figure(1)
    plt.clf()
    # plt.suptitle(relpath)
    plt.title("use plot_data function")
    plot_data(d1, x1, y1, aspect="equal")

    a = Data2D(d1, x1, y1)
    plt.figure(2)
    plt.clf()
    plt.title("From data")
    a.plot(aspect="equal")

    b = Data2D(file=wfile, ytox=220 / 1000.0, center=(0, 0))
    plt.figure(3)
    plt.clf()
    plt.title("from filename")
    b.plot(aspect="equal")

    b.save(
        os.path.join(
            outpath, os.path.basename(fn_add_subfix(relpath.as_posix(), "", ".txt"))
        ),
        makedirs=True,
    )
    b.remove_nan_frame()

    plt.figure()
    plt.title("removed nans")
    b.plot(aspect="equal")
Пример #13
0
def test_class_init():
    """test init and plot"""
    from pySurf.instrumentReader import matrixZygo_reader
    from dataIO.fn_add_subfix import fn_add_subfix
    relpath = r'test\input_data\zygo_data\171212_PCO2_Zygo_data.asc'
    outpath = r'test\results\data2D_class'

    wfile = os.path.join(os.path.dirname(__file__), relpath)
    (d1, x1, y1) = matrixZygo_reader(wfile, ytox=220 / 1000., center=(0, 0))

    plt.figure(1)
    plt.clf()
    plt.suptitle(relpath)
    plt.title('use plot_data function')
    plot_data(d1, x1, y1, aspect='equal')

    a = Data2D(d1, x1, y1)
    plt.figure(2)
    plt.clf()
    plt.title('From data')
    a.plot(aspect='equal')

    b = Data2D(file=wfile, ytox=220 / 1000., center=(0, 0))
    plt.figure(3)
    plt.clf()
    plt.title('from filename')
    b.plot(aspect='equal')

    b.save(os.path.join(outpath,
                        os.path.basename(fn_add_subfix(relpath, "", ".txt"))),
           makedirs=True)
    b.remove_nan_frame()

    plt.figure()
    plt.title('removed nans')
    b.plot(aspect='equal')
Пример #14
0
def plot_data_repeat_leveling(dlist,outfile=None,dis=True,name = ""):
    """Create a multiplot on a grid with plots of all data with
    same leveling: raw, conical, cyliindrical, sag removed by line
    
    abused function in old notebooks when type of leveling was uncertain or of interest."""

    xs,ys=find_grid_size(len(dlist),3,square=False)
    res=[]
    r=plot_data_repeat(dlist,name=name,num=1)
    res.append(r)
    if outfile:
        os.makedirs(os.path.dirname(outfile)+'\\raw\\',exist_ok=True)
        plt.savefig(fn_add_subfix(outfile,'_raw','.png',pre='raw\\'))
    if dis: display(plt.gcf())
    
    fig,axes=plt.subplots(xs,ys,num=2)
    axes=axes.flatten()
    maximize()
    res.append([])
    for i,(ll,ax) in enumerate(zip(dlist,axes)):
        plt.subplot(xs,ys,i+1,sharex=axes[0],sharey=axes[0])
        tmp=ll.copy()
        tmp.data=ll.data-fit.fitCylMisalign(ll.data)[0]
        tmp.plot(stats=True)
        res[-1].append(tmp.std())
        #plt.clim([-3,3])
        plt.clim(*(tmp.std()*np.array([-1,1])))
    for ax in axes[:len(dlist)-1:-1]:
        fig.delaxes(ax)
        #plt.pause(0.1)
    plt.suptitle(name+' CYL corrected')
    if outfile:
        os.makedirs(os.path.dirname(outfile)+'\\cyl\\',exist_ok=True)
        plt.savefig(fn_add_subfix(outfile,'_cyl','.png',pre='cyl\\'))
    if dis: display(plt.gcf())
    
    fig,axes=plt.subplots(xs,ys,num=3)
    axes=axes.flatten()
    maximize()
    res.append([])
    for i,(ll,ax) in enumerate(zip(dlist,axes)):
        plt.subplot(xs,ys,i+1,sharex=axes[0],sharey=axes[0])
        tmp=ll.copy()
        tmp.data=ll.data-fit.fitConeMisalign(ll.data)[0]
        tmp.plot(stats=True)
        res[-1].append(tmp.std())
        #plt.clim([-3,3])
        plt.clim(*(tmp.std()*np.array([-1,1])))
    for ax in axes[:len(dlist)-1:-1]:
        fig.delaxes(ax)
        #plt.pause(0.1)
    plt.suptitle(name+' CONE corrected')
    if outfile:
        os.makedirs(os.path.dirname(outfile)+'\\cone\\',exist_ok=True)
        plt.savefig(fn_add_subfix(outfile,'_cone','.png',pre='cone\\'))
    if dis: display(plt.gcf())    
    
    fig,axes=plt.subplots(xs,ys,num=4)
    axes=axes.flatten()
    maximize()
    res.append([])
    for i,(ll,ax) in enumerate(zip(dlist,axes)):
        plt.subplot(xs,ys,i+1,sharex=axes[0],sharey=axes[0])
        tmp=ll.copy()
        #tmp.data=level_data(*ll(),2)[0]
        tmp=tmp.level(2,axis=1)
        tmp.plot(stats=True)
        res[-1].append(tmp.std())
        #plt.clim([-1,1])
        plt.clim(*(tmp.std()*np.array([-1,1])))
    for ax in axes[:len(dlist)-1:-1]:
        fig.delaxes(ax)
        #plt.pause(0.1)
    plt.suptitle(name+' SAG removed by line')
    plt.tight_layout(rect=[0,0,1,0.95])
    
    if outfile:
        os.makedirs(os.path.dirname(outfile)+'\\leg\\',exist_ok=True)
        plt.savefig(fn_add_subfix(outfile,'_leg','.png',pre='leg\\'))
    if dis: display(plt.gcf())  
        
    return res
Пример #15
0
from pySurf.points import plot_points, matrix_to_points2
from pySurf.points import subtract_points, level_points
from pySurf.points import points_find_hull, crop_points, save_points, points_autoresample
from pySurf.psd2d import calculatePSD  #,plotPSDs,PSDplot
from pyProfile.profile import polyfit_profile, level_profile
from plotting.multiplots import compare_images
from dataIO.fn_add_subfix import fn_add_subfix
from dataIO.span import span
import os
from utilities.imaging import fitting as fit
from plotting.add_clickable_markers import add_clickable_markers

#gp=get_points(df,scale=gscale,center=(0,0))

pts1 = get_points(fn_add_subfix(datafile, '_shape', '.dat'), delimiter=' ')

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5

pts.shape

# In[174]:

a = np.array(np.arange(12).reshape((3, 4)))
print('a, shape ', a.shape, ':\n', a)

aa = a + np.array([float('.%02i' % i) for i in np.arange(12)]).reshape(a.shape)
print('aa, shape ', aa.shape, ':\n', aa)

#this concatenates arrays on an arbitrary axis, defaults to 0
b = np.stack([aa, aa + 100])
Пример #16
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
Пример #17
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
Пример #18
0
def psd2d_analysis(wdata,x,y,title=None,wfun=None,vrange=None,
    rmsrange=None,prange=None,fignum=5,rmsthr=None, 
    aspect='auto', ax2f=None, units=None,outname=None,norm=1,rmsnorm=True):
    """ Calculates 2D PSD as image obtained combining all profile PSDS calculated along vertical slices of data. Resulting image has size 
    If title is provided rms slice power is also calculated and plotted on three panels with figure and PSD.
    
    Return PSD as PSD2D object. 

    uses plot_rms_power(f,p,rmsrange=None) to calculate rms power.
    fignum window where to plot, if fignnum is 0 current figure is cleared,
    if None new figure is created. Default to figure 5.
    rmsrange is one or a list of frequency ranges for plotting integrated rms. Can contain None to use max or min.
    If axf2 is set to boolean or array of boolean, plot slice rms for the frequencies
    associated to rmsrange on second axis. rmsrange must be set accordingly (same number of elements).
    
    rmsthr sets a threshold for data inclusion. If rms is above the value, the line is considered to contain invalid data and is removed from output PSD.
    This makes it easy to average the returned PSDs.
    Corresponding data are still visualized in central panel, but are marked with a red cross at top of y axes.
    If multiple rms range intervals are provided, line is removed if any of them is over the threshold, but this might change in future, e.g. TODO: make it possible to add vector threshold with as many elements as rms range intervals.

    Set outname to empty string to plot without generating output.

    typical values:
    rmsrange=[[None,0.1],[0.1,0.2],[0.2,1],[1,None]]  #list of frequency intervals for rms
    ax2f=[0,1,1,0,0]             #   axis where to plot rms corresponding to intervals in rmsrange: 1 right, 0 left
    wfun  = np.hanning           #   type of windows for fourier transform
    units = ("mm","mm","$\mu$m") #   units of surface data from which PSD is calculated

    vrange_surf=([-0.5,0.5])  #color scale of surface map
    vrange_leg=([-0.05,0.05])   #color scale of legendre removed map
    prange=np.array((1e-8,1.e-1))#np.array((5e-8,1.e-5))  #color scale of 2d psd plot

    fs,ps=psd2d_analysis(levellegendre(y,wdata,2),x,y,outname="",wfun=np.hanning,
    rmsrange=rmsrange,prange=prange,ax2f=ax2f,units=units)
    """
    #2018/04/05
    # -critical renaming of plot_psd2d(wdata,x,y..) -> psd2d_analysis
    # and _plot_psd2d(f,p,x) -> plot_psd2d consistently with other routines.
    # -added title to determine if generating plot, with the intent of replacing outname.
    plt.pause(1)
    #print('cane',fignum) 
    if outname is not None:  #handle backcompatibility
        print ('psd2d_analysis WARNING: `title` replaced `outname` and output figure will be no more generated.'+
            'OUTNAME will be removed in next version, use title and save the plot after returning from routine.')
        if title is not None:
            print('outname should be not used together with title, it will be ignored.')
        else:
            title=outname
    
    if vrange is not None:
        if prange is None:
            print("""WARNING:  older versions of psd2d use vrange as range of psdvalue.
                    In updated version prange is range of psd and vrange is range for surface
                    plots. Update your code.""")

    #check compatibility with old interface
    if len(wdata.shape)==1:
        if len(y.shape)==2:
            print("WARNING: your code calling psd2d uses old call")
            print("psd2d(x,y,data), automaticly adjusted, but")
            print("update IMMEDIATELY your code to call")
            print("psd2d(data,x,y)")
            x,y,wdata=wdata,x,y

    f, p = psd2d(wdata, x, y, wfun=wfun, norm=norm, rmsnorm=rmsnorm)  # calculate PSD 2D
       
    # GENERATE OUTPUT
    if title is not None:

        if np.size(units)==1:
            units=np.repeat(units,3)

        if prange is None:
            if f[0] == 0:
                prange=span(p[1:,:])
            else:
                prange=span(p)
                if prange[0]<1e-20:  #arbitrary small value
                    print("WARNING: low limit detected in prange, can cause problems with log color scale.")
        if vrange is None:
            vrange=span(wdata)

        #plot surface map, who knows why on figure 5       
        fig=fignumber(fignum)
        #pdb.set_trace()
        #
        plt.clf()
        maximize()
        plt.draw()

        plt.suptitle(title)

        ################
        #plot Surface
        ax1=plt.subplot(311)
        plot_data(wdata,x,y,aspect=aspect,vmin=vrange[0],vmax=vrange[1],units=units,title='Surface',stats=True)
        plt.xlabel(None)
        plt.grid(1)

        ################
        #plot 2D PSD
        ax2=plt.subplot(312,sharex=ax1)
        plot_psd2d(f,p,x,prange=prange,units=units)
        if rmsrange is not None:      #plot horizontal lines to mark frequency ranges for rms extraction,
        #rms is tranformed to 2D array
            if len(np.array(rmsrange).shape)==1:  #if only one interval, make it 2D anyway
                rmsrange=[rmsrange]
            rmsrange=np.array(rmsrange)
            for fr in np.array(rmsrange):  #I want fr to be array type, even if I don't care about rmsrange this does the job
                ax2.hlines(fr[fr != None],*((span(x)-x.mean())*1.1+x.mean()))
        ax2.set_xlabel("")
        plt.xlabel(None)
        #plt.subplots_adjust(top=0.85)

        ################
        #plot rms slice
        ax3=plt.subplot(313,sharex=ax1)
        if f[0]==0: #ignore component of 0 frequency in rms calculation if present
            ff,pp=f[1:],p[1:]
        else:
            ff,pp=f,p

        rms=plot_rms_power(ff,pp,x,rmsrange=rmsrange,ax2f=ax2f,units=units)
        #pdb.set_trace()
        mask=np.isfinite(rms) #True if good. it is an array
        if rmsthr is not None:
            mask = mask & (rms  < rmsthr)
            ax3.hlines(rmsthr,*ax2.get_xlim()) #plot markers on rms chart
            ax2.plot(x[~mask],np.repeat(ax2.get_ylim()[1],len(x[~mask])),'rx') #plot markers on psd2d chart
        
        #pdb.set_trace()
        #questa era qui, ma dava errore perche' mask e' lineare
        #mask = np.all(mask,axis =0) # if any of mask is False -> False
        p[:,~mask]=np.nan
        ax3.grid(1)
        #plt.tight_layout(rect=(0, 0.03, 1, 0.95) if title else (0, 0, 1, 1))
        
        # replaced with more evolved interactive resize:
        #  plt.colorbar().remove() #dirty trick to adjust size to other panels
        def resize(event):
            box1 = ax1.get_position()
            box2 = ax2.get_position()
            box3 = ax3.get_position()
            ax2.set_position([box1.x0, box2.y0, box1.width , box2.height])
            ax2.set_adjustable("box",share=True)
            ax3.set_position([box1.x0, box3.y0, box1.width , box3.height])
            ax3.set_adjustable("box",share=True)

        cid = fig.canvas.mpl_connect('draw_event', resize)
        cid2 = fig.canvas.mpl_connect('resize_event', resize)

        resize(None)

        #plt.tight_layout()

        if outname:    #kept for compatibility, will be removed in next version
            plt.savefig(fn_add_subfix(outname,'_2dpsd','.png'))

    return f,p
Пример #19
0
def trioptimize(d1,
                d2,
                fom,
                testvals=None,
                rois=None,
                outfile=None,
                noplot=False,
                dis=True):
    """run optimizations using scale_fit2 over a set of cases
    defined by the values in matching lists of testvals (array of scaling test values) 
    and rois ([[xmin,xmax],[ymin,ymax]]). 
    
    Returns a pandas data structure with parameters and best scaling values for each case,
        with fields ['tbest','testval','roi','fom_roi'].
    
    Plot 
 
    d1 and d2 are Data2D objects.
    testvals: list of vectors to use as test values for each of the ROI
    rois:    list of rois (same len as testvals), in form [[xmin,xmax],[ymin,ymax]], 
        set to None to use for range.
    outfile:
    noplot:
    dis:
    """

    if outfile is not None:
        outname = os.path.basename(outfile)
        outfolder = os.path.dirname(outfile)
    else:
        outname = None

    plt.close('all')
    res = pd.DataFrame(
        index=['tbest', 'testval', 'roi', 'fom_roi', 'fom_initial'
               ]).transpose()

    if any_is_none(testvals):
        if fom != fom_rms:
            raise ValueError(
                'analytical fit (without testval) supported only for fom_rms')
        if testvals is None: testvals = [None] * len(rois)

    #Minimizes on each subaperture
    for i, (roi, testval) in enumerate(zip(rois, testvals)):
        name = 'crop%02i' % (
            i + 1) if outname is None else outname + '_crop%02i' % (i + 1)
        #if dis print optimization parameters
        if dis:
            print("\n\n\n===   CASE %i: %s  ===\n" % (i + 1, name))
            if roi is None:
                print('FULL APERTURE')
            else:
                print("CROP: [%.2f:%.2f] [%.2f:%.2f]" % tuple(roi[0] + roi[1]))
            print("TEST RANGE:", span(testval))
            dtest = (d1 - d2).crop(*roi) if roi is not None else d1 - d2
            fom0 = fom(*dtest())
            print("INITIAL FOM:", fom0)

        #do optimization, plot bestfit on ROI, displaying plot if dis is True
        s = scale_fit2(
            d1,
            d2,
            testval,
            dis=dis
            if roi is not None else False,  #it will plot later if no roi 
            fom=fom,
            outfile='' if outname is None else fn_add_subfix(
                outfile, '_crop%02i' % (i + 1)),
            roi=roi,
            crop=dis)  #if dis is set, plot roi, otherwise skip

        #calculate and store best fit
        ftest = fom(*((d1 - d2 * s).crop(*roi))()) if roi is not None else fom(
            *(d1 - d2 * s)())
        b = pd.Series(
            [s, testval, roi, ftest, fom0],
            index=['tbest', 'testval', 'roi', 'fom_roi',
                   'fom_initial'],  #fom_initial added 04/02
            name=name)
        res = res.append(b)

        #plot best fit case full range unless noplot
        if not noplot:
            plt.close('all')
            comp2(d1, d2 * s, roi=roi)  # plots entire area with rectangle
            dtest = (d1 - d2 * s)
            plt.tight_layout(rect=[0, 0.03, 1, 0.95])
            plt.suptitle('best factor:%6.3f, FOM surf:%6.3f' %
                         (s, fom(*dtest())))
            if outname:
                plt.savefig(
                    fn_add_subfix(outfile, '_croproi_%02i' % (i + 1), '.png'))
            if dis: display(plt.gcf())
        if dis: print("BEST SCALE: %.3f" % s, " FOM:", ftest)

    if dis: print("\n===\nSUMMARY:")
    #a=pd.DataFrame(index=['tbest','testval','roi','fom_roi']).transpose()
    for roi, r in zip(rois, res.iterrows()):
        if dis:
            if roi is None:
                print('FULL APERTURE--> BEST SCALE: ', r[1]['tbest'])
            else:
                #pdb.set_trace()
                #not sure why this is needed, but r[0] is the dataseries name, r[1] the dataseries
                print("CROP: [%.2f:%.2f] [%.2f:%.2f]" % tuple(roi[0] + roi[1]),
                      "--> BEST SCALE: ", r[1]['tbest'])
    print("=======================")

    return res
Пример #20
0
def scale_fit2(d1,
               d2,
               testval=None,
               fom=fom_rms,
               outfile='',
               roi=None,
               crop=False,
               dis=True):
    """d1 and d2 are Data2D objects. Returns value for scaling tbest of d2
    that minimizes fom(d1-d2*tbest). e.g. fom = rms of surface/slope.
    Plot rms as a function of scale factor (if testval are passed for raster scan) 
        and 4 panel plot of best result (use comp2) either cropped (if crop is True) 
        or full.
    
    if testval is set to None, best fit is determined by analytical formula (minimizing
        rms of surface difference). If tesval is array, all values are tested. 
    
    if `roi` is passed, fom is calculated on the roi only.
    `crop` flag controls the plotting. If True, only the roi is plotted and 
    color scale is adjusted accordingly. Otherwise, entire region is plotted and
    a rectangle around the roi is plotted.
    dis=True print information and display plots in notebook.
    
    all fom and stats are calculated on leveled data, ideally I want to have stats in 
    roi unleveled, but it is safer this way for now.
    """

    #dy=np.diff(d1.y)[0]
    d2 = d2.resample(d1)

    res = []
    if roi is None:
        diff = d1 - d2
        roi = [span(diff.x), span(diff.y)]  #stupid way of doing it

    if testval is None:
        #use analytical formula
        tbest = simple_regressor(d1.crop(*roi).data, d2.crop(*roi).data)
        dtest = (d1 - (d2 * tbest)).crop(*roi).level()
        rbest = fom(*dtest())
    else:
        #test all values
        for i, t in enumerate(testval):
            #test each testval, create a plot (on file only). If dis is True, print vals
            diff = d1 - d2 * t
            f = fom(*(diff.crop(*roi))())
            res.append(f)
            axes = comp2(d1, d2 * t, roi=roi)
            plt.tight_layout(rect=[0, 0.03, 1, 0.95])
            plt.suptitle('factor: %s' % t)
            if outfile:
                plt.savefig(fn_add_subfix(outfile, '_%03i' % (i + 1), '.jpg'))
            if dis: print(i, t, f)
        #select best value
        res = np.array(res)
        ibest = np.argmin(res)
        tbest = testval[np.argmin(res)]
        rbest = res[ibest]
        #make plot with rms as a function of testval
        plt.figure(5)
        plt.clf()
        plt.plot(testval, res)
        plt.title('best factor:%6.3f, FOM surf:%6.3f' % (tbest, res[ibest]))
        plt.grid()
        if outfile:
            plt.savefig((fn_add_subfix(outfile, '', '.jpg', pre='FOMtrend_')))
        if dis: display(plt.gcf())

    #plot and display (if dis) best fit data (cropped if crop is selected, full otherwise).
    if crop:
        d1 = d1.crop(*roi).level()
        d2 = d2.crop(*roi).level()
    plt.figure()
    a = comp2(d1, d2 * tbest, roi=roi)
    plt.tight_layout(rect=[0, 0.03, 1, 0.95])
    plt.suptitle('best factor:%6.3f, FOM surf:%6.3f' % (tbest, rbest))
    if dis: display(plt.gcf())
    if outfile: plt.savefig(fn_add_subfix(outfile, '_fit', '.jpg'))

    return tbest
Пример #21
0
def psd_variability(psdlist,psdrange=None,rmsrange=None,fignum=None,units=None,
    outname=None,figsize=(15,5)):
    # to be removed
    """given a list of 2d psd files plot spans of all of them on same plot.
    TODO: replace input using data rather than files. Move to 2DPSD"""

    from plotting.fignumber import fignumber   
    from pySurf.data2D import projection
    from pySurf.psd2d import rms_power 
    from scipy.stats import ttest_ind
    
    units=['mm','mm','$\mu$m']
    labels = [p.name for p in psdlist]

    #gestione rudimentale dell'output troppo stanco per pensare allo standard.
    if outname is not None:
        label=os.path.basename(outname)
        outfolder=os.path.dirname(outname)
        os.makedirs(outfolder,exist_ok=True)

    rms_v=[]
    fig=fignumber(fignum,figsize=figsize)
    plt.subplot(121)
    for (p,x,f),fn in zip(psdlist,labels):
        ps=projection(p,axis=1,span=True)
        rms_v.append(rms_power(f,p,rmsrange))
        c=plt.plot(f,ps[0],label=os.path.basename(fn)+' AVG')[0].get_color()
        plt.plot(f,ps[1],'--',label='point-wise min',c=c)
        plt.plot(f,ps[2],'--',label='point-wise max',c=c)
        #pdb.set_trace()
    plt.ylabel('axial PSD ('+units[2]+'$^2$ '+units[1]+')')
    plt.xlabel('Freq. ('+units[1]+'$^{-1}$)')
    plt.vlines(rmsrange,*plt.ylim(),label='rms range',linestyle=':')
    plt.ylim(psdrange)
    plt.loglog()
    plt.grid(1)
    plt.legend(loc=0)

    print("Statistics for %s, rms range [%6.3g,%6.3g]:"%(label,*rmsrange))
    for rms,fn in zip(rms_v,labels):
        print(os.path.basename(fn)+": rms=%6.3g +/- %6.3g (evaluated on %i profiles)"%
            (np.nanmean(rms),np.nanstd(rms),len(rms)))
    print ("--------------")
    print ("Distribution of rms: %6.3g +/- %6.3g"%(np.nanmean(rms_v,axis=1).mean(),np.nanmean(rms_v,axis=1).std()))
    print ("AGGREGATED: rms=%6.3g +/- %6.3g (evaluated on %i profiles)"%
            (np.nanmean(rms_v),np.nanstd(rms_v),np.size(rms_v)))
    if len(rms_v)==2:
        print ("Student T test t:%6.3g p:%6.3g"%ttest_ind(rms_v[0],rms_v[1]))

    l=[os.path.splitext(os.path.basename(f))[0]+" rms=%3.2g +/- %3.2g (N=%i)"%
        (np.nanmean(r),np.nanstd(r),len(r)) for f,r in zip(labels,rms_v)]
    plt.subplot(122)
    plt.hist([rr[np.isfinite(rr)] for rr in rms_v],density=True,bins=100,label=l)
    plt.legend(loc=0)
    plt.title(label+" distrib. of avg: %3.2g +/- %3.2g"%
        (np.nanmean(rms_v,axis=1).mean(),np.nanmean(rms_v,axis=1).std()))
    #handles = [Rectangle((0,0),1,1,color=c,ec="k") for c in [low,medium, high]]
    #labels= ["low","medium", "high"]
    #plt.legend(handles, labels)
    plt.tight_layout()
    if outname is not None:
        plt.savefig(fn_add_subfix(outname,'_stats','.jpg'))

    return rms_v
Пример #22
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)
Пример #23
0
def plotFEA(FEAfile, FEAreader, datafile=None, outname=None, markers=None):
    """ read FEA and resample/rebin both points and FEA on the grid defined by steps, subtract gravity from pts 
    and plot and returns the corrected points. Simulation and data are also plotted if valid. 
    If datafile is not passed only simulation data are plotted and returned.
    FEA reader is a function that accept a single argument FEAfile and return an array of points describing 
    changes in shape (x,y,dz)."""
    rebin = False

    fpts = FEAreader(FEAfile)
    if trans is not None:
        fpts = trans(fpts)
    if datafile is not None:
        pts = get_points(datafile, delimiter=' ')

        if rebin:
            pts = rebin_points(pts, steps=steps)
            fp = rebin_points(fpts, steps=steps)
        else:
            xl, yl = span(pts, axis=0)[:2, :]
            xg = np.arange(xl[0], xl[1], steps[0])
            yg = np.arange(yl[0], yl[1], steps[1])
            pts = resample_grid(pts, xg, yg)
            fp = resample_grid(fpts, xg, yg)

        pts0 = subtract_points(pts, fp)
    else:
        pts0 = pts
        pts = None

    #diagnostic plots for gravity subtraction
    if pts is not None:
        plt.figure('pts0')  #corrected
        plt.clf()
        plot_points(pts0, scatter=1, aspect='equal')
        plt.title('points from file')
        if markers is not None:
            plt.plot(markers[:, 0], markers[:, 1], '+w', label='support')

    if datafile is not None:
        plt.figure('pts')  #data
        plt.clf()
        plot_points(pts, scatter=1, aspect='equal')
        plt.title('resampled and gravity corrected')
        plt.savefig(fn_add_subfix(outname, '_corrected', '.png'))
        if markers is not None:
            plt.plot(markers[:, 0], markers[:, 1], '+w', label='support')

    plt.figure('fp')  #simulation
    plt.clf()
    plot_points(fp, scatter=1, aspect='equal')
    plt.title('gravity effect from FEA')
    if markers is not None:
        plt.plot(markers[:, 0], markers[:, 1], '+',
                 label='support')  #here x and y inverted
    plt.savefig(fn_add_subfix(outname, '_FEA', '.png'))

    if outname is not None:
        save_points(pts0, fn_add_subfix(outname, '', '.dat'))
        save_points(pts0, fn_add_subfix(outname, '_matrix', '.dat'), matrix=1)
        save_points(pts0, fn_add_subfix(outname, '_matrix', '.fits'), matrix=1)

    return pts0
Пример #24
0
    #create points to be fit from a subset of points.
    pts = get_points(datafile, delimiter=' ')
    #pts=rotate_points(pts,-np.pi/2)
    pts = crop_points(pts, (-28, 33), (-75, 65))
    pts[:, 2] = pts[:, 2] / 1000.
    c = crop_points(pts, (-28, 33), (-50, 50))  #[0:-1:1000,:]
    odr2 = (33, 220., 0, 0, 220)
    result = minimize(fom_func,
                      x0=(odr2[0:-1], ),
                      args=(c, ),
                      options={'maxiter': 1000},
                      callback=p,
                      method='Nelder-Mead')
    print('-----------------------------------')
    print('Results of fit on subset of points:')
    print(result)

    #create output results applying the value from fit to all points
    odr = result.x
    fom, deltaR, coeff = fom_func(odr, pts, retall=True)
    origin = (odr[0], 0, odr[1])
    direction = (odr[2], 1., odr[3])
    deltaR[:, 2] = deltaR[:, 2] * 1000
    print('-----------------------------------')
    print('Results of fit applied to complete set of points:')
    print('F.O.M.=%s' % (fom))

    plot_points(deltaR, vmin=-5, vmax=10, scatter=1, aspect='equal')
    save_points(deltaR, filename=fn_add_subfix(datafile, outSubfix))
    plt.savefig(fn_add_subfix(datafile, outSubfix, '.png'))