Startup
This commit is contained in:
4
script/anuschka/makeref.py
Normal file
4
script/anuschka/makeref.py
Normal file
@@ -0,0 +1,4 @@
|
||||
print caget("X06DA-OP-BPM1:SUM")
|
||||
|
||||
|
||||
print mono_beam.read()
|
||||
79
script/censlits.py
Normal file
79
script/censlits.py
Normal file
@@ -0,0 +1,79 @@
|
||||
slits = ['Primaries horizontal','Primaries Vertical',
|
||||
'ExpBox Tert. horizontal ','ExpBox Tert. vertical',
|
||||
'ExpBox Quart. horizontal','ExpBox Quart. vertical']
|
||||
|
||||
ev = get_string('Please select slits', None, slits)
|
||||
if ev is None:
|
||||
raise Exception("Aborted")
|
||||
|
||||
elif ev == slits[0]: #Primaries-Horizontal after collimating mirror and before mono
|
||||
mmot = phs # slit size
|
||||
smot = phc # slit centre
|
||||
r = 10.0 # scan half range
|
||||
pclose = r/10. # slit size for scan
|
||||
popen = 12.0 # slit size in open position
|
||||
detector = mono_beam
|
||||
#MESSAGE,'Not ready yet',/cont
|
||||
elif ev == slits[0]: #Primaries-Vertical before collimating mirror
|
||||
mmot = pvs
|
||||
smot = pvc
|
||||
r = 2.0
|
||||
pclose = r/10.
|
||||
popen = 2.0
|
||||
detector = mono_beam
|
||||
#MESSAGE,'Not ready yet',/cont
|
||||
elif ev == slits[2]: #Exposure box Tertiary slits-Horizontal before IO
|
||||
mmot = ths
|
||||
smot = thc
|
||||
r = 1.0
|
||||
pclose = r/10.0
|
||||
popen = 1.0
|
||||
detector = Channel('X06DA-ES-BM:I0', 'd')
|
||||
elif ev == slits[0]: #Exposure box Tertiary slits-Vertical
|
||||
mmot = tvs
|
||||
smot = tvc
|
||||
r = 0.4
|
||||
pclose = r/4.
|
||||
popen = .4
|
||||
detector = Channel('X06DA-ES-BM:I0', 'd')
|
||||
elif ev == slits[0]: #Exposure box Quartenary slits-Horizontal after I0
|
||||
mmot = qhs
|
||||
smot = qhc
|
||||
r = 0.4
|
||||
pclose = r/8.
|
||||
popen = .40
|
||||
detector = marcover
|
||||
#MESSAGE,'To make sure the diode is connected',/cont
|
||||
elif ev == slits[5]: #Exposure box Quartenary slits-Vertical
|
||||
mmot = qvs
|
||||
smot = qvc
|
||||
r = 0.3
|
||||
pclose = r/6.
|
||||
popen = .20
|
||||
detector = mono_beam
|
||||
#MESSAGE,'To make sure the diode is connected',/cont
|
||||
|
||||
mmot.write(pclose)
|
||||
result = lscan(smot, detector, -r,r, 20, latency = 0.5, relative = True) #SCAN,smot,-r,r,20,data=d,gfit=a,time=.5,detec=detector
|
||||
(ydata, xdata) = (result.getReadable(0), result.getPositions(0))
|
||||
|
||||
ydata = [x*1e6 for x in ydata]
|
||||
maxy = max(ydata) #MAX(y,im)
|
||||
cen =sum([ydata[i] * xdata[i] for i in range(len(ydata))]) / sum(ydata) #TOTAL(x*y) / TOTAL(y) #TODO: is right?
|
||||
|
||||
|
||||
|
||||
#OPLOT,x,GAUSSFIT(x,y,a,ESTIMATES = [maxy,cen,pclose,0,0,0],nterms=6)*1e-6, color=240,psym=6
|
||||
(n, m, s) = fit(ydata, xdata)
|
||||
|
||||
#help,mmot
|
||||
mmot.write(popen)
|
||||
|
||||
if abs(m) < 1 and abs(m-cen) < 0.5: #TODO: is a(1) the mean?
|
||||
print 'moving centre of slits to: ', m
|
||||
smot.mov(m)
|
||||
else:
|
||||
#PLOTS,cen,[0,maxy]*1e6,color=240,linestyle=1 : #TODO ?
|
||||
msg='fit failed - do you want to drive to centre of mass position: '+ cen +' ?'
|
||||
if get_option(msg, 'YesNo') == 'Yes':
|
||||
smot.mov(cen)
|
||||
90
script/check_rock.py
Normal file
90
script/check_rock.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# check_rock.com: a shell script to call idl routine to rock first or second crystal at X06DA
|
||||
# when the flux is low
|
||||
# purpose: to prevent crystal falls off the rocking curve when the temp of first crystal change.
|
||||
# 20080506 meitian
|
||||
# 20100621 mt & vo -> new CVD BPM in mono. check flux and ROCK, and then check vertical beam position and FBM
|
||||
|
||||
print "======"
|
||||
print "check&rock"
|
||||
print "======"
|
||||
# get energy first with simple calculation (i.e. not very accurate)
|
||||
THETA1 = th1.read()
|
||||
THETA2 = th2.read()
|
||||
ENERGY = get_energy()
|
||||
if int(ENERGY) < 6:
|
||||
raise Exception("No rocking optimization for lower energy for 3rd harmonics rejection")
|
||||
|
||||
# if theta1 and theta2 differ too much (>0.01deg), rock won't work well, sete should be used in this case
|
||||
# 20130614, change threshold from 0.015 to 0.02
|
||||
if abs(THETA1 + THETA2) > 0.02:
|
||||
raise Exception("Two mono crystals are not synchronized, please use 'sete()'")
|
||||
#
|
||||
# check the flux
|
||||
print "check and rock"
|
||||
BPM1C1 = caget("X06DA-OP-BPM1:CHAN1", 'd')
|
||||
BPM1C2 = caget("X06DA-OP-BPM1:CHAN2", 'd')
|
||||
BPM1C3 = caget("X06DA-OP-BPM1:CHAN3", 'd')
|
||||
BPM1C4 = caget("X06DA-OP-BPM1:CHAN4", 'd')
|
||||
BPM1 = (BPM1C1 + BPM1C2 + BPM1C3 + BPM1C4) / 4
|
||||
print "OP-BPM1 average = ", BPM1
|
||||
# if the BPM1 reading is too low, means no beam, do not rock, and quit
|
||||
# without beam, BPM1 and 2 readings are about 1.2-1.2 nA
|
||||
if BPM1 <= 2:
|
||||
raise Exception("Flux is too low, either no beam or FE shutter is not open.")
|
||||
|
||||
print "Current energy is ", ENERGY, ", mono theta2 is ", THETA2, "."
|
||||
# 20080507 number for BPM1
|
||||
# keV 7 8 9 10 11 12 13 14 15 16 17
|
||||
# BPM1 with room light: 150 140 120 110 100 90 80 80 70 50 40
|
||||
# BPM1 w/o room light: 134 123 111 95 81 70 61 54 47 40 20
|
||||
# new CVD BPM 20100621
|
||||
# 6 7 8 9 10 11 12.4 13 14 15 16 17
|
||||
# 51 65 63 57 53 48 40 37 33 27 18 6
|
||||
|
||||
# get correct threshold for different energy
|
||||
BPM1_limit = ["41", "52", "50", "44," "42", "39", "32", "30", "26", "21", "14", "4"]
|
||||
i = 0
|
||||
for i in range(12):
|
||||
n = i + 6
|
||||
if n == int(ENERGY):
|
||||
print int(ENERGY), n, i, BPM1_limit[i] #TODO: There was bug indexing here?
|
||||
BPM1_lowLimit = BPM1_limit[i]
|
||||
|
||||
|
||||
# if flux is low, rock
|
||||
if BPM1 <= BPM1_lowLimit:
|
||||
print "BPM1 reading is lower than ", BPM1_lowLimit
|
||||
print "lets rock."
|
||||
rock()
|
||||
time.sleep(2)
|
||||
else :
|
||||
print "BPM1 reading is higher than ", BPM1_lowLimit
|
||||
print "nothing to do, quit."
|
||||
print " "
|
||||
#TODO: Should abort?
|
||||
|
||||
|
||||
#==========================================================
|
||||
print "======"
|
||||
print "check and fbm"
|
||||
# check the X06DA-ES-BPM1:POSV
|
||||
|
||||
if ( eh_shutter.read() == "NOT_OPEN" ):
|
||||
raise Exception("ExpHutchShutter closed - program will exit")
|
||||
|
||||
BPM1POSV = es_beam_posv.read()
|
||||
print "Vertical beam postion at ES-BPM1: ", BPM1POSV
|
||||
# to get an integer (microns), 0.005 * 1000 / 1 with bc will do it.
|
||||
POSV = int(BPM1POSV * 1000)
|
||||
# if the POSV reading is not within +/- 8 microns means beam position is drifted, do FBM
|
||||
|
||||
# if flux is low, rock
|
||||
if POSV <= -6 or POSV >= 6 :
|
||||
print "Beam is not aligned at E-BOX BPM1"
|
||||
print "lets fix it."
|
||||
fbm()
|
||||
time.sleep(2)
|
||||
else :
|
||||
print "Beam is aligned at E-BOX BPM1,"
|
||||
print "nothing to do, quit."
|
||||
print " "
|
||||
6
script/diode_scan.py
Normal file
6
script/diode_scan.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""
|
||||
Diode scan
|
||||
"""
|
||||
|
||||
asd
|
||||
#Execute the scan: 200 steps, a1 from 0 to 40
|
||||
77
script/fbm.py
Normal file
77
script/fbm.py
Normal file
@@ -0,0 +1,77 @@
|
||||
###################################################################################################
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
#tc1 = caget('X06DA-OP-MO:TC1') # theta1 thermo couple 1
|
||||
energy = get_energy() # Mono energy
|
||||
dtz = detector_z.read()
|
||||
|
||||
if current.read() < 200:
|
||||
raise Exception ('Ring current too low')
|
||||
|
||||
if fe_absorber.read()!= 'OPEN':
|
||||
raise Exception ('FrontEndAbsorber closed') # FrontEnd absorber shutter state
|
||||
|
||||
if fe_shutter.read() != 'OPEN':
|
||||
raise Exception ('FrontendShutter closed')
|
||||
|
||||
if eh_shutter.read() != 'OPEN': # ExpHutch shutter state
|
||||
raise Exception ('ExpHutchShutter closed ')
|
||||
|
||||
if mono_energy.read()> 17.5: #Mono energy
|
||||
raise Exception ('Sorry, no feedback above 17.5 keV for now')
|
||||
|
||||
tc = 40 # 2015.09.20 quick fix by MT JW
|
||||
cur = es_beam.read()
|
||||
op1 = caget('X06DA-OP-XPM1:CHAN1', 'd')
|
||||
|
||||
if op1 < 1.0:
|
||||
sete_failed = 1
|
||||
raise Exception ('X06DA-OP-XPM1:CHAN1 < 10 - please check monochromator, frontend, primary slits, ring current and undulator - program exits')
|
||||
|
||||
# define max deviations
|
||||
dmx = 14.0 # 2 x distance mirror HR-XBPM
|
||||
ymax = 2e-3 # endwhile criterion for vertical correction
|
||||
|
||||
|
||||
if cur < tc: #check if beam is on CVD-XBPM
|
||||
sete_failed = 1
|
||||
raise Exception ('evere problem - NO BEAM ON HR-DIFFRACTOMETER XBPM')
|
||||
|
||||
# initial mirror TRY3 position
|
||||
y3i = try3.read()
|
||||
print "initial y3i: " + str(y3i)
|
||||
|
||||
# how much beam is off?
|
||||
by = es_beam_posv.read()
|
||||
print "EBOX-POSV before rock: " + str(by)
|
||||
# if beam is not off, do nothing
|
||||
if abs(by) > ymax:
|
||||
rock(th1)
|
||||
|
||||
# result of ROCK
|
||||
time.sleep(2.0)
|
||||
by = es_beam_posv.read()
|
||||
print "EBOX-POSV after rock: " + str(by)
|
||||
|
||||
# feedback
|
||||
while abs(by) >= ymax :
|
||||
by = es_beam_posv.read()
|
||||
print "current EBOX-POSV: " + str(by)
|
||||
cur = es_beam.read()
|
||||
if cur > tc:
|
||||
if (eh_shutter.read() == 'OPEN') and (abs(by) > ymax):
|
||||
if abs(by) > (50*ymax):
|
||||
raise Exception ('TODO')
|
||||
#limit mirror TRY3 movement
|
||||
y3 = try3.read()
|
||||
if abs(y3i - y3 - 1e-4 * round(by/1e-3)) > 0.008:
|
||||
raise Exception ('Feedback trying to move mirror Y3 beyond safe limit')
|
||||
try3.moveRel(-1e-4 * round(by/1e-3))
|
||||
print "current X06DA-OP-MI1:TRY3: ", y3
|
||||
time.sleep(0.25)
|
||||
|
||||
|
||||
print "TRY3 net movement: " + str(y3i-try3.read()) #print how much TRY3 moved
|
||||
|
||||
55
script/fit.py
Normal file
55
script/fit.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from mathutils import estimate_peak_indexes, fit_gaussians, create_fit_point_list, Gaussian
|
||||
import java.awt.Color as Color
|
||||
|
||||
import mathutils
|
||||
mathutils.MAX_ITERATIONS = 100000
|
||||
|
||||
def fit(ydata, xdata = None, draw_plot = True):
|
||||
if xdata is None:
|
||||
xdata = frange(0, len(ydata), 1)
|
||||
max_y= max(ydata)
|
||||
index_max = ydata.index(max_y)
|
||||
max_x= xdata[index_max]
|
||||
print "Max index:" + str(index_max),
|
||||
print " x:" + str(max_x),
|
||||
print " y:" + str(max_y)
|
||||
|
||||
if draw_plot:
|
||||
plots = plot([ydata],["data"],[xdata], title="Fit" )
|
||||
p = None if plots is None else plots[0]
|
||||
|
||||
gaussians = fit_gaussians(ydata, xdata, [index_max,])
|
||||
if gaussians[0] is None:
|
||||
if draw_plot and (p is not None):
|
||||
p.addMarker(max_x, None, "Max="+str(round(max_x,4)), Color.GRAY)
|
||||
print "Fitting error"
|
||||
return (None, None, None)
|
||||
|
||||
(norm, mean, sigma) = gaussians[0]
|
||||
if draw_plot:
|
||||
fitted_gaussian_function = Gaussian(norm, mean, sigma)
|
||||
scale_x = [float(min(xdata)), float(max(xdata)) ]
|
||||
points = max((len(xdata)+1), 100)
|
||||
resolution = (scale_x[1]-scale_x[0]) / points
|
||||
fit_y = []
|
||||
fit_x = frange(scale_x[0],scale_x[1],resolution, True)
|
||||
for x in fit_x:
|
||||
fit_y.append(fitted_gaussian_function.value(x))
|
||||
#Server
|
||||
if p is None:
|
||||
plot([ydata,fit_y],["data","fit"],[xdata,fit_x], title="Fit")
|
||||
draw_plot = False
|
||||
else:
|
||||
p.addSeries(LinePlotSeries("fit"))
|
||||
p.getSeries(1).setData(fit_x, fit_y)
|
||||
|
||||
if abs(mean - xdata[index_max]) < abs((scale_x[0] + scale_x[1])/2):
|
||||
if draw_plot:
|
||||
p.addMarker(mean, None, "Mean="+str(round(mean,4)), Color.MAGENTA.darker())
|
||||
print "Mean -> " + str(mean)
|
||||
return (norm, mean, sigma)
|
||||
else:
|
||||
if draw_plot:
|
||||
p.addMarker(max_x, None, "Max="+str(round(max_x,4)), Color.GRAY)
|
||||
print "Invalid gaussian fit: " + str(mean)
|
||||
return (None, None, None)
|
||||
86
script/flux_diode.py
Normal file
86
script/flux_diode.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# from Clemens' flux calc & Robin's paper [Owen et al, JSR 16, 2009, Silicon PIN diodes]
|
||||
#--------- formula --------------------------------------------
|
||||
# flux = I_ph * eps_Si /e/E/( 1-exp(A_Si*rsi*t_Si ) )
|
||||
# with Al and air atten:
|
||||
# flux= flux * exp(A_Al*ral*t_Al) * exp(A_air*rair*t_air)
|
||||
#
|
||||
# with A_ being the photoelectric cross sections of the materials
|
||||
|
||||
#--------- parameters -----------------------------------------
|
||||
# density of Si
|
||||
rsi = 2.33 # g/cm^3
|
||||
# density of Al
|
||||
ral = 2.699 # g/cm^3
|
||||
# density of air
|
||||
rair = 1.205e-3 # g/cm^3
|
||||
|
||||
eps_si = 3.62 # eV energy req. for charge separation in Si (generation of el/hole pairs)
|
||||
e = 1.602e-19 # As , elementary charge
|
||||
|
||||
t_si = 0.0012 # thickness of diode in cm (== 12 micron) ; [* 10000]
|
||||
t_al = 0.002 # thickness of diode in cm ; (== 20 micron)
|
||||
|
||||
#--------- input---------------------------------------------------
|
||||
|
||||
cur = float(get_string('Please enter the measured diode current [in mA]', 0.1))
|
||||
ep = float(get_string('Please enter the photon energy [in keV]', 12.4 ))
|
||||
t_si= float(get_string('Please enter the thickness of the Si layer [in micron]', t_si))
|
||||
t_si = t_si/10000. # --> cm
|
||||
t_al = float(get_string('Please enter the thickness of the Al layer [in micron, 0 if not available]', t_al))
|
||||
t_al = t_al/10000
|
||||
t_air = float(get_string('Please enter the pathway in air [in mm]', 165.+100.))
|
||||
|
||||
|
||||
#--------- calc----------------------------------------------------
|
||||
# energy deposit in Silicon
|
||||
|
||||
polys=[4.158,- 2.238, - 0.477, 0.0789]
|
||||
|
||||
hlp_si= poly(math.log10(ep), polys)
|
||||
A_Si= 10.0 ** hlp_si
|
||||
efact=math.exp(-A_Si*rsi*t_si)
|
||||
|
||||
sifact=1.0-efact
|
||||
|
||||
#help, cur, eps_si, ep
|
||||
|
||||
fl0=cur* eps_si/1.602/ep/sifact *1.e13
|
||||
|
||||
|
||||
# Aluminium attenuation
|
||||
|
||||
# ratio of photoelectric cross section to density for Aluminium
|
||||
polyal= [4.106, - 2.349, - 0.413, 0.0638 ]
|
||||
hlp_al= poly(math.log10(ep), polyal)
|
||||
A_Al= 10.0 ** hlp_al
|
||||
|
||||
# attenuation due to aluminium
|
||||
alfact=math.exp(-A_Al*ral*t_al)
|
||||
|
||||
# Air attenuation
|
||||
|
||||
# ratio of photoelectric cross section to density for air
|
||||
polyair= [3.153, - 1.026, - 2.348, 0.928]
|
||||
hlp_air= poly(math.log10(ep), polyair)
|
||||
A_air= 10.0 ** hlp_air
|
||||
|
||||
# attenuation due to air
|
||||
airfact=math.exp(-A_air*rair*t_air/10.)
|
||||
|
||||
# total flux from photocurrent
|
||||
|
||||
fl=fl0/alfact/airfact
|
||||
|
||||
f = fl
|
||||
|
||||
msg = ' Energy: ' + '%7.4f' % e + ' keV\n'
|
||||
msg = msg+ ' Diodecurrent: ' + str(cur).strip() +' mA\n'
|
||||
msg = msg+ '\n'
|
||||
msg = msg+ ' Thickness of active Si layer: ' + str(t_si*10000.).strip() + ' micron\n'
|
||||
msg = msg+ ' Thickness of Al layer in front of diode: ' + str(t_al*10000.).strip() + ' micron\n'
|
||||
msg = msg+ ' Length of path in air in front of diode: ' + str(t_air).strip() + ' mm\n'
|
||||
msg = msg+ '\n'
|
||||
msg = msg+ ' ===> flux: %8.2E photons / s' % f
|
||||
|
||||
print msg
|
||||
show_message(msg, "flux_diode", False)
|
||||
186
script/local.py
186
script/local.py
@@ -1,4 +1,184 @@
|
||||
###################################################################################################
|
||||
# Deployment specific global definitions - executed after startup.py
|
||||
###################################################################################################
|
||||
###################################################################################################
|
||||
# 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)
|
||||
|
||||
47
script/rock.py
Normal file
47
script/rock.py
Normal file
@@ -0,0 +1,47 @@
|
||||
###################################################################################################
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
#from startup import * #Not needed: executed from local
|
||||
|
||||
def rock(axis = th1, tt = 0.2, seti0 = False, dx = None, noref = False):
|
||||
"""
|
||||
"""
|
||||
#inject() #Not needed: executed from local
|
||||
if axis is None:
|
||||
axis = th1
|
||||
if noref == False:
|
||||
mono_beam_ref.write(-1.0)
|
||||
e = get_energy()
|
||||
if dx is None:
|
||||
dx = 7.5e-2/e
|
||||
|
||||
# put 'Retry deadband' to 0.00004 and 'Retries Max' to 5
|
||||
time.sleep(0.2)
|
||||
|
||||
caput(axis.channelName + '.RDBD',0.00004)
|
||||
caput(axis.channelName + '.RTRY',5)
|
||||
|
||||
print time.strftime('%X %x')
|
||||
axis_pos = axis.read()
|
||||
result = lscan(axis, mono_beam, -dx, dx, 20, latency = 0.3, relative = True)
|
||||
(ydata, xdata) = (result.getReadable(0), result.getPositions(0))
|
||||
(norm, mean, sigma) = fit(ydata, xdata)
|
||||
if (mean is not None) and (mean <= (axis_pos + dx)) and (mean >= (axis_pos - dx)):
|
||||
axis.move(mean)
|
||||
if seti0:
|
||||
time.sleep(2)
|
||||
run("setI0")
|
||||
#add after_rock BPM1:SUM as reference for monitoring monochromator thermal drift
|
||||
if (noref==False):
|
||||
time.sleep(3) # wait a bit until mono theta finish moving
|
||||
br = mono_beam.read()
|
||||
mono_beam_ref.write(br)
|
||||
print 'rock_success new mono beam at ' + str(br) + ' at ' + str(e) + ' keV'
|
||||
return True
|
||||
else:
|
||||
max_x= xdata[ydata.index(max(ydata))]
|
||||
print 'fit failed - centering on maximum: ' + str(max_x)
|
||||
axis.move(max_x)
|
||||
return False
|
||||
|
||||
14
script/rocknroll.py
Normal file
14
script/rocknroll.py
Normal file
@@ -0,0 +1,14 @@
|
||||
ei = get_energy()
|
||||
if ei < 6.0:
|
||||
print "No rocking optimization for lower energy for 3rd harmonics rejection'
|
||||
rock(th1)
|
||||
|
||||
#check beam position at EBOX and fbm if needed
|
||||
time.sleep(2.0)
|
||||
|
||||
by = es_beam_posv.read()
|
||||
if (abs(by) > 0.005):
|
||||
print by
|
||||
print 'Beam is not aligned at E-BOX BPM: do fbm.'
|
||||
run("fbm")
|
||||
|
||||
83
script/sete.py
Normal file
83
script/sete.py
Normal file
@@ -0,0 +1,83 @@
|
||||
def error(msg):
|
||||
caput(beam_err, (msg[:40]) if len(msg) > 40 else msg)
|
||||
raise Exception (msg)
|
||||
|
||||
#def sete(e, all=True, wavelengt=False):
|
||||
|
||||
|
||||
beam_err = BEAMLINE_XNAME + '-ES-DAQ:BEAM-ERROR'
|
||||
beam_set = BEAMLINE_XNAME + '-ES-DAQ:BEAM-SET'
|
||||
ring_current_cutoff = 300.0
|
||||
|
||||
if wavelength:
|
||||
e = 12.39842/e
|
||||
if e < 4.7 or e > 17.5:
|
||||
error('ERROR:Energy out of range: 4.7 to 17.5 keV')
|
||||
|
||||
print time.strftime('%X %x')
|
||||
print '... Setting energy to '+ str(e) +' keV.'
|
||||
msg = 'Working... (aiming @ '+ str(e) +' keV)'
|
||||
caput(beam_err, (msg[:40]) if len(msg) > 40 else msg)
|
||||
|
||||
if caget('ALIRF-GUN:CUR-LOWLIM', 'd') < ring_current_cutoff:
|
||||
error('ERROR:Current is too low: < ' + str(ring_current_cutoff) + 'mA')
|
||||
|
||||
if fe_absorber.read()!= 'OPEN':
|
||||
raise Exception ('FrontEndAbsorber closed') # FrontEnd absorber shutter state
|
||||
|
||||
if fe_shutter.read() != "OPEN":
|
||||
raise Exception ('FrontendShutter closed')
|
||||
|
||||
e0 = get_energy(False);
|
||||
dE = abs(e-e0)
|
||||
|
||||
print '... started to move monochromator motors'
|
||||
print '... alignment will take some minutes '
|
||||
act = 0
|
||||
|
||||
# do a setenergy to move theta 1 and 2 to calculated position in case they are not synchronized.
|
||||
theta1 = th1.read() #TODO: setpoint?
|
||||
etheta1 = a2e(abs(theta1),1,1,1,deg=True,ln=True)
|
||||
theta2 = th2.read()
|
||||
etheta2 = a2e(abs(theta2),1,1,1,deg=True,ln=False)
|
||||
if abs (etheta1-etheta2) > 0.01:
|
||||
set_energy(e)
|
||||
|
||||
|
||||
while abs(e-e0) > 3e-5/math.tan(angle(e, deg=False)): #TODO: deg==false? WHILE ABS(e-e0) GT 3e-5/TAN(ANGLE(e)) DO BEGIN
|
||||
set_energy(e)
|
||||
e0 = get_energy(False)
|
||||
|
||||
|
||||
|
||||
#----- correcting theta2 if intensity is low or if the encoder -----
|
||||
#----- differs by more than rocking curve width from theory --------
|
||||
|
||||
|
||||
# -------- for sete, /all, remove all filters
|
||||
if all:
|
||||
filter1.write("None")
|
||||
filter2.write("None")
|
||||
filter3.write("None")
|
||||
filter4.write("None")
|
||||
time.sleep(0.5)
|
||||
|
||||
#-------- rock FIRST crystal until its peak is reached -------------
|
||||
while rock(th1)==False: #TODO: #ROCK,1,dt = (dE>1.)*4e-2/e,ffail=ff
|
||||
pass
|
||||
|
||||
# finer final rock
|
||||
time.sleep(1.0)
|
||||
print 'FINER FINAL ROCK'
|
||||
rock()
|
||||
|
||||
|
||||
e0 = get_energy()
|
||||
print e0
|
||||
mono_energy.write(e0)
|
||||
print mono_energy.read()
|
||||
|
||||
caput(beam_err, 'Finito')
|
||||
caput(beam_set, 'DONE')
|
||||
|
||||
print 'sete_done'
|
||||
95
script/seteq.py
Normal file
95
script/seteq.py
Normal file
@@ -0,0 +1,95 @@
|
||||
#def seteq(e):
|
||||
|
||||
# this is sete not so quick version.
|
||||
# mono two rotation stages are not as recise as needed.
|
||||
# for quick energy change (needed for energy scan), move two thetas with same amount sometime go off the rocking curve.
|
||||
# possible solutions:
|
||||
# 1) check flux, if low , rock --> slow
|
||||
# 2) maxth1 to adjust theta1
|
||||
# 3) reduce 'Retry deadband' to 0.0001 (from 0.00004) and 'Retries Max' to 1 (from 5) --> use encoder too much will make things worse.
|
||||
# what's the flux at beginning
|
||||
Istart = mono_beam.read()
|
||||
|
||||
if e < 4.6 or e > 17.5:
|
||||
raise Exception('ERROR:Energy out of range: 4.6 to 17.5 keV')
|
||||
|
||||
if fe_absorber.read()!= 'OPEN':
|
||||
raise Exception ('FrontEndAbsorber closed') # FrontEnd absorber shutter state
|
||||
|
||||
if fe_shutter.read() != "OPEN":
|
||||
raise Exception ('FrontendShutter closed')
|
||||
|
||||
if exp_shutter.read() == 'CLOSED':
|
||||
raise Exception('Experiments hutch shutter closed - program needs beam for alignment')
|
||||
|
||||
e0 = get_energy(False)
|
||||
|
||||
|
||||
#X06DA-ES-BPM1:POSV before energy change
|
||||
eboxbpm0 = es_beam_posv.read()
|
||||
print 'X06DA-ES-BPM1 vertial feedback to max flux'
|
||||
print "X06DA-ES-BPM1:POSV BEFORE" + str(eboxbpm0)
|
||||
|
||||
#--------------- setting theta 1, 2 --------------------
|
||||
|
||||
# adjust 'Retry deadband' to 0.0001 (from 0.00004) and 'Retries Max' to 1 (from 5)
|
||||
try:
|
||||
caput(th1.channelName +'.RDBD',0.00001)
|
||||
caput(th2.channelName +'.RDBD',0.00001)
|
||||
caput(th1.channelName +'.RTRY',1)
|
||||
caput(th2.channelName +'.RTRY',1)
|
||||
|
||||
#in order to do a small energy change without rock,
|
||||
# 1) move theta2 to calculated angle
|
||||
# 2) move theta1 to exact amount as theta2 moved
|
||||
|
||||
while (abs(e-e0) > (3e-5 / math.tan(angle(e, deg=False)))):
|
||||
t1v = th1.read() #TODO: setpoint?
|
||||
t2v = th2.read()
|
||||
t2s = angle(float(e),1,1,1, deg=True)
|
||||
dt2 = t2s-t2v
|
||||
dt1 = -dt2
|
||||
t1p = t1v+dt1
|
||||
t2p = t2s # which is t2v+dt2
|
||||
print 'set angles th1, th2, relative move dt1, dt2 ', t1p, t2p, dt1, dt2
|
||||
th1.move(t1p)
|
||||
th2.move(t2p)
|
||||
e0=get_energy(False)
|
||||
time.sleep(2.0)
|
||||
Inow = mono_beam.read()
|
||||
print e, Istart, Inow
|
||||
|
||||
# feedback at BPM5
|
||||
eboxbpm = es_beam_posv.read()
|
||||
while abs(eboxbpm-eboxbpm0) > 0.002:
|
||||
if (eboxbpm-eboxbpm0) >0:
|
||||
th1.moveRel(-0.00004)
|
||||
else:
|
||||
th1.moveRel(0.00004)
|
||||
|
||||
time.sleep(1.0)
|
||||
eboxbpm = es_beam_posv.read()
|
||||
# if BPM1:POSV is too off, stop it
|
||||
if eboxbpm > 0.050:
|
||||
raise Exception("BPM1:POSV is too off")
|
||||
|
||||
# put 'Retry deadband' to 0.00004 and 'Retries Max' to 5
|
||||
# wait a bit until motor movement finished (of course, this won't work if move across large energy range. but who use seteq to do that.)
|
||||
time.sleep(0.2)
|
||||
|
||||
finally:
|
||||
caput(th1.channelName +'.RDBD',0.00004)
|
||||
caput(th2.channelName +'.RDBD',0.00004)
|
||||
caput(th1.channelName +'.RTRY',5)
|
||||
caput(th2.channelName +'.RTRY',5)
|
||||
|
||||
e0 = get_energy()
|
||||
print e0
|
||||
mono_energy.write(e0)
|
||||
print mono_energy.read()
|
||||
|
||||
|
||||
# release the token!
|
||||
#free_setetoken
|
||||
|
||||
print 'seteq_done'
|
||||
19
script/seti0.py
Normal file
19
script/seti0.py
Normal file
@@ -0,0 +1,19 @@
|
||||
s = []
|
||||
v = []
|
||||
t = []
|
||||
for i in range(10):
|
||||
s.append(caget('X06SA-OP-BPM3:SUM'))
|
||||
v.append(caget ('X06SA-OP-BPM3:POSV'))
|
||||
t.append(caget('X06SA-OP-MO:TC3'))
|
||||
time.sleep(0.09)
|
||||
|
||||
"""
|
||||
#TODO
|
||||
!x06saopbpm3y = MEAN(v)
|
||||
#dum = NEWCAPUT('X06SA-OP1-MI:BPM_IO',MEAN(S))
|
||||
|
||||
"""
|
||||
|
||||
print 'Setting I0 to '+ str(mean(s))+' +/- '+str(stdev(s))+' nA'
|
||||
print 'Setting BPM3_Y to'+ str(mean(v))+' +/- '+str(stdev(v))+' mm'
|
||||
print 'Setting TC3 to '+ str(mean(t))+' +/- '+str(stdev(t))+' mm'
|
||||
12
script/test/test.py
Normal file
12
script/test/test.py
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
show_message("My message", title = "Title", blocking = True)
|
||||
|
||||
print get_option("Choose:" , type = "YesNoCancel")
|
||||
|
||||
print get_string("Enter string:", default = "default")
|
||||
|
||||
print get_string("Choose string:", default = "default", alternatives = ["default", "alt1", "alt2"])
|
||||
|
||||
print get_string("Enter password:", password = True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user