Files
cristallina/PSSS_motion.py

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()