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
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
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))
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
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'))
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
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
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)
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='')
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)
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()
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")
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')
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
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])
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
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
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
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
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
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
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)
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
#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'))