Skip to content
Snippets Groups Projects
Commit 19bdec15 authored by Daniel Toyra's avatar Daniel Toyra
Browse files

More mirror map stuff

parent 48be2d1b
No related branches found
No related tags found
No related merge requests found
...@@ -52,7 +52,7 @@ class surfacemap(object): ...@@ -52,7 +52,7 @@ class surfacemap(object):
self.Rc = Rc self.Rc = Rc
self.zOffset = zOffset self.zOffset = zOffset
self.__interp = None self.__interp = None
self._zernikesRemoved = {} self._zernikeRemoved = {}
self._betaRemoved = None self._betaRemoved = None
if data is None: if data is None:
...@@ -84,6 +84,7 @@ class surfacemap(object): ...@@ -84,6 +84,7 @@ class surfacemap(object):
mapfile.write("%.15g " % self.data[i,j]) mapfile.write("%.15g " % self.data[i,j])
mapfile.write("\n") mapfile.write("\n")
@property @property
def betaRemoved(self): def betaRemoved(self):
return self._betaRemoved return self._betaRemoved
...@@ -93,15 +94,15 @@ class surfacemap(object): ...@@ -93,15 +94,15 @@ class surfacemap(object):
self._betaRemoved = v self._betaRemoved = v
@property @property
def zernikesRemoved(self): def zernikeRemoved(self):
return self._zernikesRemoved return self._zernikeRemoved
@zernikesRemoved.setter @zernikeRemoved.setter
def zernikesRemoved(self, v): def zernikeRemoved(self, v):
''' '''
v = tuple(m,n,amplitude) v = tuple(m,n,amplitude)
''' '''
self._zernikesRemoved["%i%i" % (v[0],v[1])] = v self._zernikeRemoved["%i%i" % (v[0],v[1])] = v
@property @property
def data(self): def data(self):
...@@ -397,6 +398,41 @@ class surfacemap(object): ...@@ -397,6 +398,41 @@ class surfacemap(object):
return fig return fig
def rms(self, w=None):
if w is None:
return math.sqrt((self.data[self.notNan]**2).sum())/self.notNan.sum()
else:
R = self.find_radius(unit='meters')
if w>=R:
return math.sqrt((self.data[self.notNan]**2).sum())/self.notNan.sum()
else:
rho = self.createPolarGrid()[0]
inside = np.zeros(self.data.shape,dtype=bool)
tmp = rho<w
inside[tmp] = self.notNan[tmp]
return math.sqrt((self.data[inside]**2).sum())/inside.sum()
def avg(self, w=None):
if w is None:
tot = self.data[self.notNan].sum()
sgn = np.sign(tot)
return sgn*math.sqrt(sgn*tot)/self.notNan.sum()
else:
R = self.find_radius(unit='meters')
if w>=R:
tot = self.data[self.notNan].sum()
sgn = np.sign(tot)
return sgn*math.sqrt(sgn*tot)/self.notNan.sum()
else:
rho = self.createPolarGrid()[0]
inside = np.zeros(self.data.shape,dtype=bool)
tmp = rho<w
inside[tmp] = self.notNan[tmp]
tot = self.data[inside].sum()
sgn = np.sign(tot)
return sgn*math.sqrt(sgn*tot)/inside.sum()
def find_radius(self, method = 'max', unit='points'): def find_radius(self, method = 'max', unit='points'):
''' '''
Estimates the radius of the mirror in the xy-plane. Estimates the radius of the mirror in the xy-plane.
...@@ -571,7 +607,7 @@ class surfacemap(object): ...@@ -571,7 +607,7 @@ class surfacemap(object):
m = (k-1)*2 m = (k-1)*2
Z = A[k]*zernike(m, 2, rho, phi) Z = A[k]*zernike(m, 2, rho, phi)
self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan] self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan]
self.zernikesRemoved = (m, 2, A[k]) self.zernikeRemoved = (m, 2, A[k])
# Estimating radius of curvature # Estimating radius of curvature
Rc = znm2Rc([a*self.scaling for a in A], R) Rc = znm2Rc([a*self.scaling for a in A], R)
elif zModes=='astigmatism' or zModes=='Astigmatism': elif zModes=='astigmatism' or zModes=='Astigmatism':
...@@ -579,17 +615,17 @@ class surfacemap(object): ...@@ -579,17 +615,17 @@ class surfacemap(object):
m = (k-1)*2 m = (k-1)*2
Z = A[k]*zernike(m, 2, rho, phi) Z = A[k]*zernike(m, 2, rho, phi)
smap.data[self.notNan] = self.data[self.notNan]-Z[self.notNan] smap.data[self.notNan] = self.data[self.notNan]-Z[self.notNan]
self.zernikesRemoved = (m, 2, A[k]) self.zernikeRemoved = (m, 2, A[k])
Rc = znm2Rc([a*self.scaling for a in A[::2]], R) Rc = znm2Rc([a*self.scaling for a in A[::2]], R)
elif zModes=='defocus' or zModes=='Defocus': elif zModes=='defocus' or zModes=='Defocus':
Z = A[1]*zernike(0, 2, rho, phi) Z = A[1]*zernike(0, 2, rho, phi)
self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan] self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan]
self.zernikesRemoved = (0, 2, A[1]) self.zernikeRemoved = (0, 2, A[1])
Rc = znm2Rc(A[1]*self.scaling, R) Rc = znm2Rc(A[1]*self.scaling, R)
self.Rc = Rc self.Rc = Rc
return self.Rc, self.zernikesRemoved return self.Rc, self.zernikeRemoved
def rmSphericalSurf(self, Rc0, w=None, zOff=None, isCenter=[False,False]): def rmSphericalSurf(self, Rc0, w=None, zOff=None, isCenter=[False,False]):
...@@ -652,7 +688,7 @@ class surfacemap(object): ...@@ -652,7 +688,7 @@ class surfacemap(object):
x0 = 0 x0 = 0
y0 = 0 y0 = 0
Z = self.createSphere(Rc,X,Y,zOff,x0,y0) Z = self.createSurface(Rc,X,Y,zOff,x0,y0)
if w is None: if w is None:
# Mean squared difference between map and the created sphere. # Mean squared difference between map and the created sphere.
...@@ -691,14 +727,14 @@ class surfacemap(object): ...@@ -691,14 +727,14 @@ class surfacemap(object):
self.center = (self.center[0] + x0/self.step_size[0], self.center = (self.center[0] + x0/self.step_size[0],
self.center[1] + y0/self.step_size[1]) self.center[1] + y0/self.step_size[1])
# Creating fitted sphere # Creating fitted sphere
Z = self.createSphere(self.Rc, X, Y, self.zOff, x0, y0) Z = self.createSurface(self.Rc, X, Y, self.zOff, x0, y0)
# Subtracting sphere from map # Subtracting sphere from map
self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan] self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan]
return self.Rc, self.zOff, self.center return self.Rc, self.zOff, self.center
# Subtracting fitted sphere from mirror map. # Subtracting fitted sphere from mirror map.
else: else:
# Creating fitted sphere # Creating fitted sphere
Z = self.createSphere(self.Rc,X,Y,self.zOff) Z = self.createSurface(self.Rc,X,Y,self.zOff)
# Subtracting sphere from map # Subtracting sphere from map
self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan] self.data[self.notNan] = self.data[self.notNan]-Z[self.notNan]
return self.Rc, self.zOff return self.Rc, self.zOff
...@@ -818,9 +854,9 @@ class surfacemap(object): ...@@ -818,9 +854,9 @@ class surfacemap(object):
def createSphere(self,Rc,X,Y,zOffset=0,x0=0,y0=0,xTilt=0,yTilt=0,isPlot=False): def createSurface(self,Rc,X,Y,zOffset=0,x0=0,y0=0,xTilt=0,yTilt=0,isPlot=False):
''' '''
Creating spherical surface. Creating surface.
Inputs: Rc, X, Y, zOffset=0, x0=0, y0=0, xTilt=0, yTilt=0, isPlot=False Inputs: Rc, X, Y, zOffset=0, x0=0, y0=0, xTilt=0, yTilt=0, isPlot=False
Rc - Radius of curvature, and center of sphere on z-axis in case zOffset=0. [m] Rc - Radius of curvature, and center of sphere on z-axis in case zOffset=0. [m]
...@@ -841,7 +877,8 @@ class surfacemap(object): ...@@ -841,7 +877,8 @@ class surfacemap(object):
# Adjusting for tilts and offset # Adjusting for tilts and offset
Z = zOffset + (X*np.tan(xTilt) + Y*np.tan(yTilt))/self.scaling Z = zOffset + (X*np.tan(xTilt) + Y*np.tan(yTilt))/self.scaling
# Adjusting for spherical shape. # Adjusting for spherical shape.
Z = Z + (Rc - np.sqrt(Rc**2 - (X-x0)**2 - (Y-y0)**2))/self.scaling if Rc !=0 and Rc is not None:
Z = Z + (Rc - np.sign(Rc)*np.sqrt(Rc**2 - (X-x0)**2 - (Y-y0)**2))/self.scaling
if isPlot: if isPlot:
import pylab import pylab
...@@ -874,9 +911,11 @@ class surfacemap(object): ...@@ -874,9 +911,11 @@ class surfacemap(object):
''' '''
print('Preparing phase map for Finesse...') print('Preparing phase map for Finesse...')
print(' rms = {:.3f} nm'.format(self.rms(w)))
print(' avg = {:.3f} nm'.format(self.avg(w)))
# Factor that scales surface height to nm. # Factor that scales surface height to nm.
nm_scaling = self.scaling*1.0e9 nm_scaling = self.scaling*1.0e9
print(' Centering...') print(' Centering...')
self.recenter() self.recenter()
print(' New center (x0, y0) = ({:.2f}, {:.2f})'. print(' New center (x0, y0) = ({:.2f}, {:.2f})'.
...@@ -889,11 +928,15 @@ class surfacemap(object): ...@@ -889,11 +928,15 @@ class surfacemap(object):
format(before[1], before[0], self.size[1], self.size[0])) format(before[1], before[0], self.size[1], self.size[0]))
print(' New center (x0, y0) = ({:.2f}, {:.2f})'. print(' New center (x0, y0) = ({:.2f}, {:.2f})'.
format(self.center[0],self.center[1])) format(self.center[0],self.center[1]))
print(' rms = {:.3f} nm'.format(self.rms(w)))
print(' avg = {:.3f} nm'.format(self.avg(w)))
# Radius of mirror in xy-plane. # Radius of mirror in xy-plane.
R = self.find_radius(unit='meters') R = self.find_radius(unit='meters')
self.plot()
print(' Removing curvatures...') print(' Removing curvatures...')
# --------------------------------------------------------
if w is None: if w is None:
Rc, znm = self.remove_curvature(method='zernike', zModes = 'defocus') Rc, znm = self.remove_curvature(method='zernike', zModes = 'defocus')
print(' Removed Z20 with amplitude A20 = {:.2f} nm'.format(znm['02'][2])) print(' Removed Z20 with amplitude A20 = {:.2f} nm'.format(znm['02'][2]))
...@@ -903,26 +946,37 @@ class surfacemap(object): ...@@ -903,26 +946,37 @@ class surfacemap(object):
if w >= w_max: if w >= w_max:
w = w_max-max(self.step_size) w = w_max-max(self.step_size)
print(' Weigthing radius too large, setting w = {0:.4f} m'.format(w)) print(' Weigthing radius too large, setting w = {0:.4f} m'.format(w))
Rc, zOff = self.remove_curvature(method='sphere', w=w) Rc, A0 = self.remove_curvature(method='sphere', w=w)
# Equivalent Zernike (n=2,m=0) amplitude. # Equivalent Zernike (n=2,m=0) amplitude.
A20 = Rc2znm(Rc,R)/self.scaling A20 = Rc2znm(Rc,R)/self.scaling
self.zernikeRemoved = (0,2,A20)
# Adding A20 to zOff because: Z(n=2,m=0) = A20*(r**2 - 1) # Adding A20 to zOff because: Z(n=2,m=0) = A20*(r**2 - 1)
zOff = zOff+A20 A0 = A0+A20
print(' Removed Rc = {0:.2f} m'.format(Rc) ) print(' Removed Rc = {0:.2f} m'.format(Rc) )
print(' Equivalent Z(n=2,m=0) amplitude A20 = {0:.2f} nm'.format(A20)) print(' Equivalent Z(n=2,m=0) amplitude A20 = {0:.2f} nm'.format(A20))
print(' rms = {:.3e} nm'.format(self.rms(w)))
print(' avg = {:.3e} nm'.format(self.avg(w)))
self.plot()
print(' Removing offset...') print(' Removing offset...')
# --------------------------------------------------------
if w is None: if w is None:
A00 = self.rmZernike(0,0) A00 = self.rmZernike(0,0)
print(' Removed Z00 with amplitude A00 = {:.2f} nm'.format(A00) ) print(' Removed Z00 with amplitude A00 = {:.2f} nm'.format(A00) )
else: else:
A0 = self.removeOffset(w) zOff = self.removeOffset(w)
zOff = zOff + A0 A0 = A0 + zOff
print(' Removed offset, A00 = {0:.4f} nm'.format(zOff)) print(' Removed offset (A00) = {0:.4f} nm'.format(zOff))
print(' rms = {:.3e} nm'.format(self.rms(w)))
print(' avg = {:.3e} nm'.format(self.avg(w)))
self.plot()
print(' Removing piston...') print(' Removing tilts...')
# --------------------------------------------------------
if w is None: if w is None:
A1 = self.zernikeConvol(1)[1] A1 = self.zernikeConvol(1)[1]
rho,phi=self.createPolarGrid() rho,phi=self.createPolarGrid()
...@@ -932,17 +986,101 @@ class surfacemap(object): ...@@ -932,17 +986,101 @@ class surfacemap(object):
Z.append(zernike(1,1,rho,phi)) Z.append(zernike(1,1,rho,phi))
for k in range(2): for k in range(2):
self.data[self.notNan] = self.data[self.notNan]-A1[k]*Z[k][self.notNan] self.data[self.notNan] = self.data[self.notNan]-A1[k]*Z[k][self.notNan]
self.zernikesRemoved = (2*k-1,1,A1[k]) self.zernikeRemoved = (2*k-1,1,A1[k])
print(' Removed Z1{:d} with amplitude A1{:d} = {:.2f} nm'. print(' Removed Z1{:d} with amplitude A1{:d} = {:.2f} nm'.
format(2*k-1,2*k-1,A1[k]) ) format(2*k-1,2*k-1,A1[k]) )
ybeta = np.arctan(A1[0]*self.scaling/R) ybeta = np.arctan(A1[0]*self.scaling/R)
xbeta = np.arctan(A1[1]*self.scaling/R) xbeta = np.arctan(A1[1]*self.scaling/R)
self.betaRemoved = (xbeta,ybeta) self.betaRemoved = (xbeta,ybeta)
print(' Equivalent tilt in radians: ybeta = {:.2e} rad'.format(ybeta)) print(' Equivalent tilt in radians: xbeta = {:.2e} rad'.format(xbeta))
print(' xbeta = {:.2e} rad'.format(xbeta)) print(' ybeta = {:.2e} rad'.format(ybeta))
else: else:
pass X,Y = np.meshgrid(self.x,self.y)
r2 = X**2 + Y**2
def f(p):
# This is used in simtools, why?
#p[0] = p[0]*1.0e-9
#p[1] = p[1]*1.0e-9
Z = self.createSurface(0,X,Y,p[2],0,0,p[0],p[1])
if w is None:
res = math.sqrt(((self.data[self.notNan]-Z[self.notNan])**2).sum())/self.notNan.sum()
else:
weight = 2/(math.pi*w**2) * np.exp(-2*r2[self.notNan]/w**2)
res = math.sqrt((weight*(self.data[self.notNan]-Z[self.notNan])**2).sum())/weight.sum()
return res
xbeta = 0
ybeta = 0
offset = 0
params = [xbeta,ybeta,offset]
opts = {'xtol': 1.0e-8, 'ftol': 1.0e-8, 'maxiter': 2000, 'disp': False}
out = minimize(f, params, method='Nelder-Mead', options=opts)
xbeta = out['x'][0]
ybeta = out['x'][1]
offset = out['x'][2]
Z = self.createSurface(0,X,Y,offset,0,0,xbeta,ybeta)
self.data[self.notNan] = self.data[self.notNan] - Z[self.notNan]
self.betaRemoved = (xbeta, ybeta)
# Equivalent Zernike amplitude
A1 = R*np.tan(np.array([ybeta,xbeta]))/self.scaling
self.zernikeRemoved = (-1,1,A1[0])
self.zernikeRemoved = (1,1,A1[1])
A0 = A0 + offset
self.zernikeRemoved = (0,0,A0)
print(' Tilted surface removed:')
print(' xbeta = {:.2e} rad'.format(xbeta))
print(' ybeta = {:.2e} rad'.format(ybeta))
print(' z-offset = {:.2e} nm'.format(offset))
print(' Equivalent Zernike amplitudes:')
print(' A(1,-1) = {:.2f} nm'.format(A1[0]))
print(' A(1, 1) = {:.2f} nm'.format(A1[1]))
print(' rms = {:.3e} nm'.format(self.rms(w)))
print(' avg = {:.3e} nm'.format(self.avg(w)))
self.plot()
if xyOffset is not None:
print(' Offsetting mirror center in the xy-plane...')
# --------------------------------------------------------
self.center = (self.center[0] + xyOffset[0]/self.step_size[0],
self.center[1] + xyOffset[1]/self.step_size[1])
print(' New mirror center (x0, y0) = ({:.2f}, {:.2f})'.format(self.center[0],self.center[1]))
print(' Writing phase map to file...')
# --------------------------------------------------------
filename = self.name + '_finesse.txt'
self.write_map(filename)
print(' Phase map written to file {:s}'.format(filename))
self.plot()
print(' Writing result information to file...')
filename = self.name + '_finesse_info.txt'
self.writeResults(filename)
print(' Result written to file {:s}'.format(filename))
# Add "create aperture map"
def writeResults(self, filename):
'''
Writing results to file. Not yet finished.
'''
import time
with open(filename,'w') as mapfile:
mapfile.write('---------------------------------------\n')
mapfile.write('Map: {:s}\n'.format(self.name))
mapfile.write('Date: {:s}\n'.format(time.strftime("%d/%m/%Y %H:%M:%S")))
mapfile.write('---------------------------------------\n')
mapfile.write('Diameter: {:.2f} cm\n'.format(self.find_radius(unit='meters')/100.0))
# mapfile.write('Offset (Z00): {:.2f}'.format(self.zernikeRemoved['00'][2]))
def removeOffset(self, r): def removeOffset(self, r):
...@@ -969,7 +1107,7 @@ class surfacemap(object): ...@@ -969,7 +1107,7 @@ class surfacemap(object):
rho = rho/R rho = rho/R
Z00 = zernike(0, 0, rho, phi) Z00 = zernike(0, 0, rho, phi)
self.data[self.notNan] = self.data[self.notNan]-A0*Z00[self.notNan] self.data[self.notNan] = self.data[self.notNan]-A0*Z00[self.notNan]
self.zernikesRemoved = (0, 0, A0) self.zernikeRemoved = (0, 0, A0)
return A0 return A0
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment