This commit is contained in:
2016-03-17 10:54:59 +01:00
parent 0b90ffd6a8
commit 0f1bf29a8e
19 changed files with 641 additions and 84 deletions

View File

@@ -1,16 +1,17 @@
#Wed Jan 20 15:37:49 CET 2016
#Thu Mar 17 10:47:20 CET 2016
autoSaveScanData=true
createSessionFiles=false
dataLayout=default
dataPath={data}/{year}_{month}/{date}/{date}_{time}_{exec}
dataProvider=default
dataScanFlushRecords=true
dataScanStrategy=default
devicePoolFile={config}/devices.properties
deviceUpdateStrategyFile={config}/update.properties
logDaysToLive=-1
logLevel=Info
logLevelConsole=Off
logPath={logs}/{date}_{time}
scanStreamingPort=-1
serverEnabled=true
serverPort=8080
simulation=false
@@ -21,5 +22,5 @@ userAuthenticator=
userManagement=false
versionTrackingEnabled=true
versionTrackingLogin=
versionTrackingManual=false
versionTrackingRemote=git@git.psi.ch\:pshell_config/x06da.git
versionTrackingManual=true
versionTrackingRemote=https\://git.psi.ch/pshell_config/x06da.git

View File

@@ -1,4 +1,5 @@
bpm1=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-BPM1:POSV|Read||true
es_beam=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-BPM1:SUM|Read||true
es_beam_posv=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-BPM1:POSV|Read||true
current=ch.psi.pshell.epics.ChannelDouble|ARIDI-PCT:CURRENT|Read||true
i0=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-I0:READOUT 6|Read||true
diode=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-DIODE:READOUT|Read||true
@@ -9,6 +10,9 @@ beam_stop_pos=ch.psi.pshell.epics.BinaryPositioner|X06DA-ES-BS:SET-POS X06DA-ES-
det_cover=ch.psi.pshell.epics.DiscretePositioner|X06DA-ES-PILCOV:SET|Read||true
backlight_pos=ch.psi.pshell.epics.BinaryPositioner|X06DA-ES-BL:SET-POS X06DA-ES-BL:GET-POS|Read||true
frontlight_enable=ch.psi.pshell.epics.BinaryPositioner|X06DA-ES-FL:ENABLE|Read||true
fe_absorber=ch.psi.pshell.epics.BinaryPositioner|X06DA-FE-AB1:OPEN_EPS|||
fe_shutter=ch.psi.pshell.epics.BinaryPositioner|X06DA-FE-PH1:OPEN_EPS|||
eh_shutter=ch.psi.pshell.epics.BinaryPositioner|X06DA-OP-ST1:OPEN_EPS|||
filter1=ch.psi.pshell.epics.DiscretePositioner|X06DA-ES-FI1:SET X06DA-ES-FI1:GET|||true
filter2=ch.psi.pshell.epics.DiscretePositioner|X06DA-ES-FI2:SET X06DA-ES-FI2:GET|||true
filter3=ch.psi.pshell.epics.DiscretePositioner|X06DA-ES-FI3:SET X06DA-ES-FI3:GET|||true
@@ -34,11 +38,29 @@ cryo_jet_tans=ch.psi.pshell.epics.Motor|X06DA-ES-CJ:TRX1|||true
aperture_x=ch.psi.pshell.epics.Motor|X06DA-ES-KBOX:TRX1|||true
collimator_x=ch.psi.pshell.epics.Motor|X06DA-ES-KBOX:TRX2|||true
diode_z=ch.psi.pshell.epics.Motor|X06DA-ES-KBOX:TRZ3|||true
marcover=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-KBOX:SIG-RAW|||true
fluo_monitor=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-BM:I0|||true
#beamstop=ch.psi.pshell.device.MotorGroupDiscretePositioner|beamstop_x beamstop_y beamstop_z|||
mono_beam=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-BPM1:SUM|Read||true
mono_beam_ref=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-MO:MONOBEAM|||
mono_energy=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-MO:E-GET|||true
slithop=ch.psi.pshell.epics.Slit|X06DA-OP-SH1:TRX2 X06DA-OP-SH1:TRX1|||true
pvs=ch.psi.pshell.epics.ChannelDouble|X06DA-FE-SVsize|||false
pvc=ch.psi.pshell.epics.ChannelDouble|X06DA-FE-SVcenter|||false
phs=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-SHsize|||
phc=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-SHcenter|||
ths=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SH1:TRX1|||
thc=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SH1:TRX2|||
tvs=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SV1:TRY1|||
tvc=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SV1:TRY2|||
qhs=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SH2:TRX1|||
qhc=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SH2:TRX2|||
qvs=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SV2:TRY1|||
qvc=ch.psi.pshell.epics.ChannelDouble|X06DA-ES-SV2:TRY2|||
th1=ch.psi.pshell.epics.Motor|X06DA-OP-MO1:ROX1|||true
th2=ch.psi.pshell.epics.Motor|X06DA-OP-MO1:ROX2|||true
th1_encoder=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-MO1:ECX1|Read||false
th2_encoder=ch.psi.pshell.epics.ChannelDouble|X06DA-OP-MO1:ECX2|Read||false
try3=ch.psi.pshell.epics.Motor|X06DA-OP-MI1:TRY3|||true
slit1h_size=ch.psi.pshell.epics.Motor|X06DA-ES-SH1:TRX1|||true
slit1h_center=ch.psi.pshell.epics.Motor|X06DA-ES-SH1:TRX2|||true

14
devices/bpm1v.properties Normal file
View File

@@ -0,0 +1,14 @@
#Fri Feb 19 14:38:26 CET 2016
defaultSpeed=NaN
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=NaN
minSpeed=NaN
minValue=NaN
offset=0.0
precision=-1
resolution=NaN
scale=1.0
unit=null

14
devices/phc.properties Normal file
View File

@@ -0,0 +1,14 @@
#Mon Feb 22 17:00:46 CET 2016
defaultSpeed=NaN
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=NaN
minSpeed=NaN
minValue=NaN
offset=0.0
precision=-1
resolution=NaN
scale=1.0
unit=null

14
devices/phs.properties Normal file
View File

@@ -0,0 +1,14 @@
#Mon Feb 22 17:00:46 CET 2016
defaultSpeed=NaN
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=NaN
minSpeed=NaN
minValue=NaN
offset=0.0
precision=-1
resolution=NaN
scale=1.0
unit=null

14
devices/pvc.properties Normal file
View File

@@ -0,0 +1,14 @@
#Mon Feb 22 17:07:43 CET 2016
defaultSpeed=NaN
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=NaN
minSpeed=NaN
minValue=NaN
offset=0.0
precision=-1
resolution=NaN
scale=1.0
unit=null

14
devices/pvs.properties Normal file
View File

@@ -0,0 +1,14 @@
#Mon Feb 22 17:07:43 CET 2016
defaultSpeed=NaN
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=NaN
minSpeed=NaN
minValue=NaN
offset=0.0
precision=-1
resolution=NaN
scale=1.0
unit=null

79
script/censlits.py Normal file
View 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
View 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 " "

View File

@@ -3,31 +3,31 @@
###################################################################################################
tc1 = caget('X06DA-OP-MO:TC1') # theta1 thermo couple 1
#tc1 = caget('X06DA-OP-MO:TC1') # theta1 thermo couple 1
energy = get_energy() # Mono energy
dtz = caget('X06DA-ES-DET:TRZ1') # detector Z- position
dtz = detector_z.read()
if current.read() < 200:
raise Exception ('Ring current too low')
if caget('X06DA-FE-AB1:OPEN_EPS','i') == 0:
if fe_absorber.read()!= 'OPEN':
raise Exception ('FrontEndAbsorber closed') # FrontEnd absorber shutter state
if caget('X06DA-FE-PH1:OPEN_EPS','i') == 0: # FrontEnd shutter state
raise Exception ('FrontEndShutter closed')
if fe_shutter.read() != 'OPEN':
raise Exception ('FrontendShutter closed')
if caget('X06DA-OP-ST1:OPEN_EPS','i') == 0: # ExpHutch shutter state
if eh_shutter.read() != 'OPEN': # ExpHutch shutter state
raise Exception ('ExpHutchShutter closed ')
if caget(('X06DA-OP-MO:E-GET'),'d') > 17.5: #Mono energy
raise Exception ('Sorry, no feedback above 17.5 keV for now')
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 = caget('X06DA-ES-BPM1:SUM','d')
cur = es_beam.read()
op1 = caget('X06DA-OP-XPM1:CHAN1', 'd')
if op1 < 1.0:
sete_failed = 1
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
@@ -36,15 +36,15 @@ ymax = 2e-3 # endwhile criterion for vertical correction
if cur < tc: #check if beam is on CVD-XBPM
sete_failed = 1
sete_failed = 1
raise Exception ('evere problem - NO BEAM ON HR-DIFFRACTOMETER XBPM')
# initial mirror TRY3 position
y3i = try3.read()
y3i = try3.read()
print "initial y3i: " + str(y3i)
# how much beam is off?
by = bpm1.read()
by = es_beam_posv.read()
print "EBOX-POSV before rock: " + str(by)
# if beam is not off, do nothing
if abs(by) > ymax:
@@ -52,17 +52,16 @@ if abs(by) > ymax:
# result of ROCK
time.sleep(2.0)
by = bpm1.read()
by = es_beam_posv.read()
print "EBOX-POSV after rock: " + str(by)
# feedback
while abs(by) >= ymax :
by = bpm1.read()
by = es_beam_posv.read()
print "current EBOX-POSV: " + str(by)
cur = caget('X06DA-ES-BPM1:SUM','d')
cur = es_beam.read()
if cur > tc:
ehs = caget('X06DA-OP-ST1:OPEN_EPS','i') # make sure that shutter is open
if (ehs > 0) and (abs(by) > ymax):
if (eh_shutter.read() == 'OPEN') and (abs(by) > ymax):
if abs(by) > (50*ymax):
raise Exception ('TODO')
#limit mirror TRY3 movement

View File

@@ -1,7 +1,7 @@
from mathutils import estimate_peak_indexes, fit_gaussians, create_fit_point_list, Gaussian
import java.awt.Color as Color
def fit(ydata, xdata = None):
def fit(ydata, xdata = None, draw_plot = True):
if xdata is None:
xdata = frange(0, len(ydata), 1)
max_y= max(ydata)
@@ -13,24 +13,26 @@ def fit(ydata, xdata = None):
gaussians = fit_gaussians(ydata, xdata, [index_max,])
(norm, mean, sigma) = gaussians[0]
if draw_plot:
p = plot([ydata],["data"],[xdata], title="Fit" )[0]
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))
p.addSeries(LinePlotSeries("fit"))
p.getSeries(1).setData(fit_x, fit_y)
p = plot([ydata],["data"],[xdata], context="Fit" )[0]
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))
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 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)
p.addMarker(mean, None, "Mean="+str(round(mean,4)), Color.MAGENTA.darker())
return (norm, mean, sigma)
else:
p.addMarker(max_x, None, "Max="+str(round(max_x,4)), Color.GRAY)
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
View 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)

View File

@@ -4,6 +4,10 @@
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):
@@ -24,12 +28,114 @@ def angle(e,h=1.0,k=1.0,l=1.0, deg =True, ln = False,bent = False):
a = a/dtor if deg else a
return a
def get_energy(debug_msg = True):
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
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")
@@ -47,6 +153,21 @@ def rocknroll():
"""
"""
run("rocknroll")
def censlits():
"""
"""
run("censlits")
def flux_diode():
"""
"""
run("flux_diode")
def sete(e, all=True, wavelengt=False):
run("sete", {"e":e, "all":all, "wavelengt":wavelengt})
def seteq(e):
runq("seteq", {"e":e})
import ch.psi.pshell.device.ReadonlyRegisterBase as ReadonlyRegisterBase

View File

@@ -4,14 +4,14 @@
#from startup import * #Not needed: executed from local
def rock(axis = th1, ffail = False, tt = 0.2, seti0 = False, dx = None, noref = False):
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:
caput('X06DA-OP-MO:MONOBEAM', -1 )
mono_beam_ref.write(-1.0)
e = get_energy()
if dx is None:
dx = 7.5e-2/e
@@ -24,17 +24,11 @@ def rock(axis = th1, ffail = False, tt = 0.2, seti0 = False, dx = None, noref =
print time.strftime('%X %x')
axis_pos = axis.read()
result = lscan(axis, mono_beam, -dx, dx, 20, latency = 0.3, relative = True, context = None, before_read = None, after_read = None)
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)
else:
print 'fit failed - centering on maximum'
max_x= xdata[ydata.index(max(ydata))]
axis.move(max_x)
if not ffail:
if seti0:
time.sleep(2)
run("setI0")
@@ -42,7 +36,12 @@ def rock(axis = th1, ffail = False, tt = 0.2, seti0 = False, dx = None, noref =
if (noref==False):
time.sleep(3) # wait a bit until mono theta finish moving
br = mono_beam.read()
caput('X06DA-OP-MO:MONOBEAM', br)
mono_beam_ref.write(br)
print 'rock_success new mono beam at ' + str(br) + ' at' + str(e) + ' keV'
return true
else:
print 'fit failed - centering on maximum'
max_x= xdata[ydata.index(max(ydata))]
axis.move(max_x)
return false

View File

@@ -6,7 +6,7 @@ rock(th1)
#check beam position at EBOX and fbm if needed
time.sleep(2.0)
by = bpm1.read()
by = es_beam_posv.read()
if (abs(by) > 0.005):
print by
print 'Beam is not aligned at E-BOX BPM: do fbm.'

View File

@@ -3,16 +3,14 @@ def error(msg):
raise Exception (msg)
#def sete(e, all=True, wavelengt=False):
e = 0
all = False
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
e = 12.39842/e
if e < 4.7 or e > 17.5:
error('ERROR:Energy out of range: 4.7 to 17.5 keV')
@@ -22,34 +20,33 @@ 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')
error('ERROR:Current is too low: < ' + str(ring_current_cutoff) + 'mA')
if caget('X06DA-FE-AB1:CLOSE_EPS') == 'CLOSE':
error('ERROR:ABSORBER closed; aborting...')
if caget('X06DA-FE-PH1:OPEN_EPS') != "OPEN":
error('ERROR:FE Shutter closed; aborting...')
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
act = 0
# do a setenergy to move theta 1 and 2 to calculated position in case they are not synchronized.
theta1 = caget('X06DA-OP-MO1:ROX1.RBV', 'd')
theta1 = th1.read() #TODO: setpoint?
etheta1 = a2e(abs(theta1),1,1,1,True)
theta2 = caget('X06DA-OP-MO1:ROX2.RBV', 'd')
theta2 = th2.read()
etheta2 = a2e(ABS(theta2),1,1,1,True)
if abs (etheta1-etheta2) > 0.01:
set_energy(e)
while abs(e-e0) > 3e-5/tan(angle(e)):
set_energy(e)
e0 = get_energy(False)
while abs(e-e0) > 3e-5/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)
@@ -59,16 +56,15 @@ while abs(e-e0) > 3e-5/tan(angle(e)):
# -------- for sete, /all, remove all filters
if all:
caput('X06DA-ES-FI1:SET',0)
caput('X06DA-ES-FI2:SET',0)
caput('X06DA-ES-FI3:SET',0)
caput('X06DA-ES-FI4:SET',0)
filter1.write("None")
filter2.write("None")
filter3.write("None")
filter4.write("None")
time.sleep(0.5)
#-------- rock FIRST crystal until its peak is reached -------------
ff = 1
while ff:
rock() #TODO: #ROCK,1,dt = (dE>1.)*4e-2/e,ffail=ff
while rock(th1)==False: #TODO: #ROCK,1,dt = (dE>1.)*4e-2/e,ffail=ff
pass
# finer final rock
time.sleep(1.0)
@@ -77,10 +73,9 @@ rock()
e0 = get_energy()
caput('X06DA-OP-MO:E-GET',e0)
print e0
print ''
print caget('X06DA-OP-MO:E-GET')
mono_energy.write(e0)
print caget(mono_energy.read())
caput(beam_err, 'Finito')
caput(beam_set, 'DONE')

View File

@@ -1,2 +1,94 @@
def seteq(e):
pass
#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)
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)))): #TODO: deg==false? WHILE ABS(e-e0) GT 3e-5/TAN(ANGLE(e)) DO BEGIN
t1v = th1.read() #TODO: setpoint?
t2v = th2.read()
t2s = angle(float(e),1,1,1)
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)
eo=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)
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 caget(mono_energy.read())
# release the token!
#free_setetoken
print 'seteq_done'

View File

@@ -9,8 +9,9 @@ for i in range(10):
"""
#TODO
!x06saopbpm3y = MEAN(v)
!x06saopbpm3y = MEAN(v)
#dum = NEWCAPUT('X06SA-OP1-MI:BPM_IO',MEAN(S))
"""
print 'Setting I0 to '+ str(mean(s))+' +/- '+str(stdev(s))+' nA'

View File

@@ -1,7 +1,7 @@
show_message("My message", title = "Title", blocking = True)
print get_option("Choose:" , option_type = SwingUtils.OptionType.YesNoCancel)
print get_option("Choose:" , type = "YesNoCancel")
print get_string("Enter string:", default = "default")