184 lines
5.5 KiB
Python
184 lines
5.5 KiB
Python
###################################################################################################
|
|
# Deployment specific global definitions - executed after startup.py
|
|
###################################################################################################
|
|
|
|
BEAMLINE_XNAME = "X06DA"
|
|
|
|
dtor = math.pi /180.0
|
|
|
|
for d in [pvs, pvc, phs, phc, ths, thc, tvs, tvc, qhs, qhc, qvs, qvc]:
|
|
d.setBlockingWrite(True)
|
|
|
|
|
|
def a2e(t,h=1.0,k=1.0,l=1.0, deg =True, ln = False):
|
|
lncorr= 2.e-4 if ln else 0.0
|
|
d0=2 * 5.43102 * (1.0-lncorr) / math.sqrt(h**2+k**2+l**2)
|
|
tt= (t * dtor) if (deg or (t>1.0)) else t
|
|
return 12.39842 / (d0*math.sin(tt))
|
|
|
|
def angle(e,h=1.0,k=1.0,l=1.0, deg =True, ln = False,bent = False):
|
|
lncorr = 2.e-4 if ln else 0.0
|
|
d0 =2 * 5.43102 * (1.0-lncorr) / math.sqrt(h**2+k**2+l**2)
|
|
a = math.asin(12.39842/d0/e)
|
|
if bent:
|
|
rho = 2*19.65*8.35/28*math.sin(a)
|
|
dt = 0.2e-3/rho*0.279
|
|
d0 = 2*5.43102*(1+dt)/math.sqrt(h**2+k**2+l**2)
|
|
a = math.asin(12.39842/d0/e)
|
|
a = a/dtor if deg else a
|
|
return a
|
|
|
|
def get_energy(debug_msg = True):
|
|
t2 = th2.position
|
|
e = a2e(abs(t2))
|
|
if debug_msg:
|
|
print 'Energy [keV]:'+ str(e) + ' Wavelength [A]:' + str(12.39842/e)
|
|
return e
|
|
|
|
def set_energy(e, debug_msg = True):
|
|
e = float(e)
|
|
if e< 4.7 or e > 18.0:
|
|
raise Exception ("please select an energy between 4.7 an 18 keV")
|
|
t1e = th1_encoder.read()
|
|
t2e = th2_encoder.read()
|
|
t1v = th1.read()
|
|
t2v = th2.read()
|
|
t1s = angle(e,1,1,1,ln=True)
|
|
t2s = angle(e,1,1,1)
|
|
|
|
# calculate the corrections later, after
|
|
# calibration of encoders
|
|
dt1 = 0.
|
|
dt2 = 0.
|
|
|
|
# it is better to move both crystals by the same amount. however,
|
|
# if one motor got stuck and the other did not, we should not move
|
|
# them by the same amount but each according to its calculated deltha theta
|
|
t1p = -t1s
|
|
t2p = t2s
|
|
|
|
if debug_msg:
|
|
print 'set angles th1=' + str(t1p) + " th2=" + str(t2p)
|
|
th1.move(t1p) #TODO: simultaneous move?
|
|
th2.move(t2p)
|
|
th1.waitReady(-1)
|
|
th2.waitReady(-1)
|
|
if debug_msg:
|
|
print 'done set energy'
|
|
|
|
|
|
def shopen():
|
|
exp_shutter.write("OPEN")
|
|
|
|
def shclose():
|
|
exp_shutter.write("CLOSED")
|
|
|
|
def vfoc (dx=0.1):
|
|
#scan,'dfy',0,2*dx,25,/fit,det='des',dat=d
|
|
motor = cy #TODO: Is right? original was not relative; motor channel was X06DA-ES-DF1:TRY-VAL
|
|
sensor = mono_beam #TODO: sensor is not clear since set det to des(X06DA-ES-KBOX:SIG-RAW) but parameter is called 'detector' in scan: is default mono_beam used?
|
|
|
|
result = lscan(motor, sensor, -dx, dx, 25, latency = 0.3, relative = True) #TODO: range is 0, 2*dx?
|
|
(ydata, xdata) = (result.getReadable(0), result.getPositions(0))
|
|
|
|
from mathutils import deriv, fit_gaussians, Gaussian, get_values
|
|
d = [x*1e6 for x in deriv(ydata, xdata)]
|
|
gaussians = fit_gaussians(d, xdata , [d.index(max(d)) ,])
|
|
(n, m, s) = gaussians[0]
|
|
fitted_gaussian_function = Gaussian(n, m, s)
|
|
g = get_values(fitted_gaussian_function,xdata)
|
|
plot((ydata, d, g), ("Sensor", "Deriv", "Gauss Fit"), (xdata,xdata,xdata))
|
|
#PLOT,d(0,*),deriv(reform(d(1,*))*1e6)
|
|
#oplot,d(0,*),gaussfit(reform(d(0,*)),deriv(reform(d(1,*))*1e6),a,nterm=5),ps=-6
|
|
print 'CENTRE ',m
|
|
print 'FWHM microns',s*2354.
|
|
motor.move(m) #?motor.move(-dx+a(1))
|
|
#WM,'mb1' #WHAT for?
|
|
#WM,'mb2'
|
|
return (n, m, s)
|
|
|
|
def knife():
|
|
pvc0 = pvc.read()
|
|
pvs0 = pvs.read()
|
|
try:
|
|
step = 0.175
|
|
pvc.write(pvc0 - 3.*step)
|
|
pvs.write(0.1)
|
|
c = []
|
|
for i in range(5):
|
|
pvc.write(pvc0 + step * i)
|
|
a = vfoc()
|
|
c.apppend(a[1])
|
|
print 'mean',mean(c)
|
|
print 'stdev',stdev(c)
|
|
finally:
|
|
pvc.write(pvc0)
|
|
pvs.write(pvs0)
|
|
|
|
def knifescan(motor, ll, hl, n=25):
|
|
try:
|
|
shopen()
|
|
time.sleep(1.0)
|
|
result = lscan(motor, marcover, ll, hl, n, latency = 0.3, relative = True)
|
|
#scan, motor, ll, hl, n,det='marcover',dat=d
|
|
(ydata, xdata) = (result.getReadable(0), result.getPositions(0))
|
|
d = deriv(ydata, xdata)
|
|
#inversed #IF MOTOR EQ 'dfx' THEN sign = -1. ELSE sign = 1 #TODO
|
|
if motor in []:
|
|
d = [x*-1.0 for x in d]
|
|
gaussians = fit_gaussians(d, xdata , [d.index(max(d)) ,])
|
|
(n, m, s) = gaussians[0]
|
|
|
|
#PLOT,D(0,*), SIGN*DERIV(d(1,*)), THICK=2
|
|
#OPLOT, d(0,*), GAUSSFIT(d(0,*),SIGN*DERIV(d(1,*)),a),col=150
|
|
plot((ydata, d, g), ("Sensor", "Deriv", "Gauss Fit"), (xdata,xdata,xdata))
|
|
print 'Centre [scanunits]',m
|
|
print 'FWHM [scanunits]',s*2.3542 #sigma to FWHM factor is 2.3542
|
|
finally:
|
|
shclose()
|
|
|
|
run("fit")
|
|
run("rock")
|
|
#run("sete")
|
|
#run("seteq")
|
|
|
|
|
|
|
|
def fbm():
|
|
"""
|
|
"""
|
|
run("fbm")
|
|
|
|
def rocknroll():
|
|
"""
|
|
"""
|
|
run("rocknroll")
|
|
|
|
def censlits():
|
|
"""
|
|
"""
|
|
run("censlits")
|
|
|
|
def flux_diode():
|
|
"""
|
|
"""
|
|
run("flux_diode")
|
|
|
|
def sete(e, all=True, wavelength=False):
|
|
run("sete", {"e":e, "all":all, "wavelength":wavelength})
|
|
|
|
def seteq(e):
|
|
run("seteq", {"e":e})
|
|
|
|
|
|
def check_rock():
|
|
run("check_rock")
|
|
|
|
|
|
import ch.psi.pshell.device.ReadonlyRegisterBase as ReadonlyRegisterBase
|
|
class EnergyReader(ReadonlyRegisterBase):
|
|
def doRead(self):
|
|
return get_energy(False)
|
|
|
|
add_device(EnergyReader("energy",3), True)
|
|
|
|
energy.polling = 1000 |