294 lines
9.3 KiB
Python
294 lines
9.3 KiB
Python
#!/usr/bin/env python
|
|
#*-----------------------------------------------------------------------*
|
|
#| |
|
|
#| Copyright (c) 2014 by Paul Scherrer Institute (http://www.psi.ch) |
|
|
#| |
|
|
#| Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
|
#*-----------------------------------------------------------------------*
|
|
'''
|
|
motion procedures for PSSS:
|
|
|
|
mode:
|
|
0: homing
|
|
1: calc energy and SPECTRUM_X out of camera arm angle
|
|
move CamPosX out of CristBendRot
|
|
'''
|
|
|
|
from __future__ import print_function
|
|
from errno import ENETRESET
|
|
import logging, sys, os, json
|
|
import CaChannel,time
|
|
import numpy as np
|
|
|
|
|
|
class PSSS:
|
|
|
|
def __init__(self, args):
|
|
# import pdb; pdb.set_trace()
|
|
# sys.exit()
|
|
# {'mode': 0, 'stdout': True, 'var': []}
|
|
# {'mode': 5, 'stdout': True, 'var': ['SARFE10-PSSS059']}
|
|
|
|
self.args=args
|
|
prefix=self.args.var[0]
|
|
prefix=prefix[0:prefix.find('-')+1]
|
|
self.prefix=prefix
|
|
#print('Prefix='+prefix)
|
|
self.pv=dict()
|
|
|
|
def getPv(self,name):
|
|
try:
|
|
pv=self.pv[name]
|
|
except KeyError:
|
|
prefix=self.prefix
|
|
pv = CaChannel.CaChannel(prefix+name) ;pv.searchw()
|
|
self.pv[name]=pv
|
|
return pv
|
|
|
|
def moveLimit(self,m,val):
|
|
self.moveAbs(m,val)
|
|
|
|
def waitMotionDone(self,m):
|
|
s=m+'.DMOV'
|
|
pv=self.getPv(s)
|
|
sys.stdout.write('wait motion '+s+' ');sys.stdout.flush();
|
|
while pv.getw()==0:
|
|
sys.stdout.write('.');sys.stdout.flush();
|
|
time.sleep(.1)
|
|
print('done');
|
|
|
|
def setPos(self,m,ofs):
|
|
pvSET=self.getPv(m+'.SET')
|
|
pvVAL=self.getPv(m+'.VAL')
|
|
pvSET.putw(1)#Set
|
|
print('set ofset to %f'%ofs)
|
|
pvVAL.putw(ofs) #set value (without move)
|
|
time.sleep(.1) # wait for safety
|
|
pvSET.putw(0)#Use
|
|
time.sleep(.1) # wait for safety
|
|
|
|
def moveAbs(self,m,val):
|
|
pvVAL=self.getPv(m+'.VAL')
|
|
pvVAL.putw(val) #set position and move
|
|
|
|
def homing(self):
|
|
pvNameLst=('PSSS055:MOTOR_ROT_X1',
|
|
'PSSS055:MOTOR_X1',
|
|
'PSSS055:MOTOR_Y1',
|
|
'PSSS055:MOTOR_PROBE',
|
|
'PSSS059:MOTOR_X5',
|
|
'PSSS059:MOTOR_Y5',
|
|
'PSSS059:MOTOR_Z5',
|
|
'PSSS059:MOTOR_X3',
|
|
'PSSS059:MOTOR_Y3')
|
|
|
|
pvHOME = self.getPv('PSSS059:HOMING.VAL')
|
|
if pvHOME.getw(1) == 1:
|
|
print('homing still in progress. abort new procedure')
|
|
#return
|
|
pvHOME.putw(1)#homing in progress
|
|
|
|
try:
|
|
pvHomr=self.getPv(pvNameLst[0]+'.HOMR')
|
|
pvHomr.putw(1)#homing MOTOR_ROT_X1
|
|
self.waitMotionDone(pvNameLst[0])
|
|
|
|
homing=(
|
|
(1,200,10,0), # PSSS055:MOTOR_X1 Home on +limit switch to +10mm
|
|
(2,10,4.475,2.22), # PSSS055:MOTOR_Y1 Home on +limit switch to +4.475mm
|
|
(3,50,0,-9), # PSSS055:MOTOR_PROBE Home on +limit switch to +0mm
|
|
(4,80,35,0), # PSSS059:MOTOR_X5 Home on +limit switch to +35mm
|
|
(5,30,10,0), # PSSS059:MOTOR_Y5 Home on +limit switch to +10mm
|
|
# (6,20,8.9,0), # PSSS059:MOTOR_Z5 Home on +limit switch to +8.9mm Set HLM to 10, LLM to -2mm
|
|
(7,30,1,0), # PSSS059:MOTOR_X3 Home on +limit switch to +10mm
|
|
(8,30,1,-1.4), # PSSS059:MOTOR_Y3 Home on +limit switch to +10mm
|
|
)
|
|
for idx,mvLim,setPos,mvPos in homing:
|
|
pvName=pvNameLst[idx]
|
|
print('homing %s %f %f %f'%(pvName,mvLim,setPos,mvPos))
|
|
self.moveLimit(pvName,mvLim)
|
|
|
|
for idx,mvLim,setPos,mvPos in homing:
|
|
pvName=pvNameLst[idx]
|
|
self.waitMotionDone(pvName)
|
|
self.setPos(pvName,setPos)
|
|
|
|
time.sleep(2);print ("sleep 2 sec.")
|
|
for idx,mvLim,setPos,mvPos in homing:
|
|
pvName=pvNameLst[idx]
|
|
self.moveAbs(pvName,mvPos)
|
|
|
|
for idx,mvLim,setPos,mvPos in homing:
|
|
pvName=pvNameLst[idx]
|
|
self.waitMotionDone(pvName)
|
|
|
|
|
|
except AssertionError as e: #BaseException as e:
|
|
print(e)
|
|
pvHOME.putw(3)#homing failed
|
|
else:
|
|
pvHOME.putw(2)#homing done
|
|
|
|
|
|
def set_energy_motor(self,energy2motor,scan=False, rotWait=False):
|
|
crystalType=self.getPv('PSSS059:CRYSTAL_SP').getw()
|
|
#crystalType=2
|
|
#print(crystalType)
|
|
#print(type(crystalType))
|
|
if crystalType==0: return
|
|
# 0 None
|
|
# 1 Si(111)R155
|
|
# 2 Si(220)R75
|
|
# 3 Si(220)R145
|
|
# 4 Si(220)R200
|
|
# 5 Si(333)R155
|
|
|
|
#load lut
|
|
fnXtlLst=(None,"Si111R155","Si220R75","Si220R145","Si220R200","Si333R155")
|
|
#print(__file__)
|
|
base=os.path.dirname(__file__)
|
|
fn=os.path.join(base,'lut'+fnXtlLst[crystalType]+'.txt')
|
|
lut= np.genfromtxt(fn, delimiter='\t',names=True)
|
|
#lut
|
|
#lut.dtype
|
|
#lut[1]['Energy']
|
|
#lut['Energy']
|
|
#lut=np.genfromtxt(fn, delimiter='\t',skip_header=1)
|
|
if energy2motor:
|
|
energy =self.getPv('PSSS059:ENERGY').getw()
|
|
#energy =6000
|
|
gratingType=self.getPv('PSSS055:GRATING_SP').getw()
|
|
#gratingType=3
|
|
camPosX='CamPosX'
|
|
if gratingType in(1,2):camPosX+='_100nm'
|
|
elif gratingType==3:camPosX+='_150nm'
|
|
elif gratingType==4:camPosX+='_200nm'
|
|
|
|
camArmRot =np.interp(energy,lut['Energy'],lut['CamArmRot'])
|
|
cristBendRot=np.interp(energy,lut['Energy'],lut['CristBendRot'])
|
|
camPosX =np.interp(energy,lut['Energy'],lut[camPosX])
|
|
evPerPix =np.interp(energy,lut['Energy'],lut['EvPerPix'])
|
|
else:
|
|
camArmRot=self.getPv('PSSS059:MOTOR_ROT_X4').getw()
|
|
idx=~np.isnan(lut['CamArmRot'])
|
|
lutCamArmRot=lut['CamArmRot'][idx]
|
|
energy =np.interp(camArmRot,lutCamArmRot[::-1],lut['Energy'][idx][::-1])
|
|
evPerPix =np.interp(camArmRot,lutCamArmRot[::-1],lut['EvPerPix'][idx][::-1])
|
|
|
|
#camera: 2560 x 2160
|
|
n=2560
|
|
i=np.arange(n)-n/2
|
|
spctr_x=energy+i*evPerPix
|
|
pv=self.getPv('PSSS059:SPECTRUM_X')
|
|
pv.putw(spctr_x)
|
|
|
|
pv=self.getPv('PSSS059:SPECTRUM_Y')
|
|
mu=2560./2
|
|
sigma=100.
|
|
x=np.arange(2560.)
|
|
spctr_y= 1000.*np.exp(-( (x-mu)**2 / ( 2.0 * sigma**2 ) ) )
|
|
pv.putw(spctr_y)
|
|
|
|
if energy2motor:
|
|
print('energy2motor: camArmRot: %g cristBendRot: %g camPosX:%g evPerPix:%g'%(camArmRot,cristBendRot,camPosX,evPerPix))
|
|
pv=self.getPv('PSSS059:MOTOR_ROT_X4')
|
|
pv.putw(camArmRot)
|
|
pv=self.getPv('PSSS059:MOTOR_ROT_X3')
|
|
pv.putw(cristBendRot)
|
|
if rotWait == True:
|
|
self.waitMotionDone('PSSS059:MOTOR_ROT_X3')
|
|
if scan == False: # if True the camera X position will not be changed
|
|
pv=self.getPv('PSSS059:MOTOR_X5')
|
|
pv.putw(camPosX)
|
|
else:
|
|
print('motor2energy: energy: %g evPerPix:%g'%(energy,evPerPix))
|
|
pv=self.getPv('PSSS059:ENERGY')
|
|
pv.putw(energy)
|
|
|
|
def grating2motor(self):
|
|
energy =self.getPv('PSSS059:ENERGY').getw()
|
|
gratingType=self.getPv('PSSS055:GRATING_SP').getw()
|
|
if gratingType==0:
|
|
print('no grating')
|
|
girderX=0.
|
|
else:
|
|
base=os.path.dirname(__file__)
|
|
fn=fn=os.path.join(base,'lutGirderXTrans.txt')
|
|
lut= np.genfromtxt(fn, delimiter='\t',names=True)
|
|
|
|
d={1:'100nm',2:'100nm',3:'150nm',4:'200nm'}
|
|
print(gratingType)
|
|
grtStr=d[gratingType]
|
|
|
|
girderX =np.interp(energy,lut['Energy'],lut[grtStr])
|
|
|
|
print("girderX:%g"%(girderX))
|
|
pv=self.getPv('PSSS059:MOTOR_X2')
|
|
pv.putw(girderX)
|
|
|
|
|
|
if __name__=='__main__':
|
|
from optparse import OptionParser, IndentedHelpFormatter
|
|
class MyFormatter(IndentedHelpFormatter):
|
|
'helper class for formating the OptionParser'
|
|
|
|
def __init__(self):
|
|
IndentedHelpFormatter.__init__(self)
|
|
|
|
def format_epilog(self, epilog):
|
|
if epilog:
|
|
return epilog
|
|
else:
|
|
return ""
|
|
|
|
def parse_args():
|
|
'main command line interpreter function'
|
|
(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>3 else sys.argv[0])+' '
|
|
exampleCmd=('MYPREFIX',
|
|
)
|
|
epilog=__doc__+'''
|
|
Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
|
|
|
fmt=MyFormatter()
|
|
parser=OptionParser(epilog=epilog, formatter=fmt)
|
|
parser.add_option('-m', '--mode', type="int", help='move instead of homing', default=0)
|
|
parser.add_option('-s', '--stdout', action="store_true", help='log to stdout instead of file')
|
|
|
|
(args, other)=parser.parse_args()
|
|
#print(args,other)
|
|
args.var=other
|
|
#args.var=('SARFE10-',)
|
|
|
|
fn='/afs/psi.ch/intranet/Controls/scratch/'+os.path.basename(__file__)+'_'+os.environ.get('USER')+'.log'
|
|
if not args.stdout:
|
|
print('output redirected to file:\n'+fn)
|
|
stdoutBak=sys.stdout
|
|
sys.stdout = open(fn, 'a+')
|
|
print('*'*30+'\n'+time.ctime()+': run on host:'+os.environ.get('HOSTNAME'))
|
|
print('Args:'+str(args)+' '+str(args.var))
|
|
sys.stdout.flush()
|
|
|
|
psss=PSSS(args)
|
|
if args.mode==0:
|
|
psss.homing()
|
|
elif args.mode==1:
|
|
psss.set_energy_motor(energy2motor=True)
|
|
elif args.mode==2:
|
|
psss.set_energy_motor(energy2motor=False)
|
|
elif args.mode==3:
|
|
psss.grating2motor()
|
|
elif args.mode==4:
|
|
psss.set_energy_motor(energy2motor=True, scan=True)
|
|
elif args.mode==5:
|
|
psss.set_energy_motor(energy2motor=True, scan=True,rotWait=True)
|
|
print('PSSS_motion done.')
|
|
|
|
return
|
|
|
|
|
|
#os.environ['EPICS_CA_ADDR_LIST']='localhost'
|
|
#os.environ['EPICS_CA_ADDR_LIST']='172.26.0.255 172.26.2.255 172.26.8.255 172.26.16.255 172.26.24.255 172.26.32.255 172.26.40.255 172.26.110.255 172.26.111.255 172.26.120.255 129.129.242.255 129.129.243.255'
|
|
|
|
parse_args()
|
|
|