#%TITLE% CHKBEAM.MAC
#%NAME%
# Macros for checking beam presence during scans.
#
#%CATEGORY% X-ray beam, scans
#
#%OVERVIEW%
# These macros implement beam checking during scans. When activated
# (by %B%onbeamchk%B%) all standard scans are affected.
# After each scan step the counting rate of the monitor is calculated.
# If it drops below a certain high threshold (the default is 80% of the
# monitor value during the
# previous counting interval) it is assumed that the beam was lost and
# the program goes into a loop in which counting is repeated and the
# monitor rate is periodically checked. The loop is exited and the scan
# is resumed when the monitor rate becomes stable and greater than a low
# threshold (defaulted to 10% of the value before the beam lost).
# The thresholds can be changed by setting global variables (see below).%BR%
# In order to avoid perturbances due to fast monitor fluctuations the
# monitor rate is filtered by an algorithm that adds an extra waiting time
# defaulted to 5 minutes.%BR%
# This checking procedure requires a beam monitor that measures the actual
# intensity of the beam. The variable %B%MON%B% must be set to the
# scaler used as a monitor, as selected by the %B%counters%B% macro.
# If possible an integrating monitor, as a counting detector or an analog
# detector followed by a F/V converter, should be used.%BR%
# With the current version it is possible to use analog signals loaded into
# pseudocounters like signals acquired by means of ADC's without integration.
# When it is possible, the macros try to detect whether the monitor is
# an integrating device or not. In the case of the %B%waitforbeam%B% macro,
# the user must add an extra parameter to signal that the monitor is
# analog.%BR%
# The global variables %B%BEAMCHK_ON%B% and %B%BEAMCHK_FLAG%B% give extra
# information when these macros are used inside other macros or command
# files.%BR%
# %B%BEAMCHK_ON%B% is set whenever the beam checking mode is active.%BR%
# %B%BEAMCHK_FLAG%B% is set to 1 to indicate a `beam lost
# condition'. Non standard scan macros can use this variable to detect beam
# losses but it is their responsability to set it to zero before counting.%BR%
# The global variable BEAMCHK_TAU contains the waiting time in seconds
# (300 seconds by default).%BR%
# The high and low thresholds can be set to values different from the defaults
# (80% and 10% respectively) by assigning new values to the global variables
# BEAMCHK_HI and BEAMCHK_LO. Positive numbers represent absolute thresholds
# while negative numbers represent values relative to the monitor rate.
# For instance: BEAMCHK_HI=1000 represent a high theshold of 1000 monitor
# counts while BEAMCHK_HI=-0.5 represent a threshold of 50% of the current
# monitor rate.
#
#%EXAMPLE%
# %DL%
# %DT%onbeamchk
# %DD%Activates beam checking.
# %DT%offbeamchk
# %DD%Cancels beam checking.
# %DT%waitforbeam 5 1e6
# %DD%Waits until the monitor counts accumulated in 5 seconds stabilize
# around one million (200000 c/s).
# %DT%waitforbeam 1 1e6 analog
# %DD%Loops counting for 1 second until the monitor value stabilizes
# around one million (analog value).
# %XDL%
#
#%END%
#%UU% [<counting_interval> [<monitor_counts> ["analog"]]
#%MDESC%
# Activates the beam checking feature.%BR%
# If <monitor_counts> is not especified, the macro estimates the current
# monitor rate and the type of monitor device (analog or integrating).%BR%
# If both <counting_interval> and <monitor_counts> are given, the monitor
# rate is evaluated from these values. In such a case the monitor is
# supposed to be by default an integrating device. This can overriden by
# setting as third parameter the literal "analog".%BR%
#
def onbeamchk '{
global MON_ANALOG FILT_MON_RATE
local t m
t = ($1)
m = ($2)
if (m <= 0){
count_em (t?t:COUNT)/2
waitcount
get_counts
MON_RATE = (MON >= 0 && S[sec]!=0)? S[MON]/S[sec] : 0
count_em (t?t:COUNT)
waitcount
get_counts
MON_ANALOG = (MON >= 0 && S[MON] != 0 && S[sec] != 0 && \
MON_RATE/(S[MON]/S[sec]) > 1.5)
} else {
S[sec] = t
if (MON >= 0)
S[MON] = m
MON_ANALOG = ("$3" == "analog")
}
if (MON<0 || S[sec]==0 || (MON_RATE=MON_ANALOG?S[MON]:S[MON]/S[sec])<=0 || \
MON == sec) {
# rdef chk_beam "break"
cdef("_chk_beamc","","beam","delete")
FILT_MON_RATE = 0
print "ERROR: Beam check not activated. "
print "The beam is down or the timer and the monitor are not properly set up."
exit
}
printf("Beam check is ON. ")
_onbeamchk
}'
#%IU%
#%MDESC%
# Activates the beam checking feature. This macro is called
# from %B%onbeamchk%B% and %B%waitforbeam%B%.
#
def _onbeamchk '
global BEAMCHK_FLAG BEAMCHK_ON
global BEAMCHK_THRESH_HI BEAMCHK_THRESH_LO
global BEAMCHK_LO BEAMCHK_HI BEAMCHK_TAU
if (!BEAMCHK_LO) BEAMCHK_LO=-0.1
if (!BEAMCHK_HI) BEAMCHK_HI=-0.8
if (!BEAMCHK_TAU) BEAMCHK_TAU = 300
FILT_MON_RATE = MON_RATE
BEAMCHK_THRESH_HI = BEAMCHK_HI < 0 ? -BEAMCHK_HI*FILT_MON_RATE : BEAMCHK_HI
BEAMCHK_THRESH_LO = BEAMCHK_LO < 0 ? -BEAMCHK_LO*FILT_MON_RATE : BEAMCHK_LO
S[MON]=0
if (MON_ANALOG) {
printf("Analog monitor \`%s\' (%s), threshold value: %g\n", \
cnt_name(MON), cnt_mne(MON), BEAMCHK_THRESH_HI)
} else {
printf("Integrating monitor \`%s\' (%s), threshold rate: %g/s\n", \
cnt_name(MON), cnt_mne(MON), BEAMCHK_THRESH_HI)
}
BEAMCHK_ON = 1
#def chk_beam "local flag delay wtunit wtunitl; if (__chk_beam()) break;;"
cdef("_chk_beamc","_chk_chkbeam\n","beam")
'
def _chk_chkbeam '{
local flag delay wtuni wtunitl
ret = __chk_beam()
if (!ret) return(0)
}'
#%IU%
#%MDESC%
# This is the macro function that does the job. It returns "True" if the
# counting was ok and "False" if it has to be repeated.
#
def __chk_beam () '{
local nfilt wtime relmonrate bmess
if (!BEAMCHK_ON)
return(1)
if (!S[sec]){
nfilt = 1
MON_RATE = 0
} else {
nfilt = (BEAMCHK_TAU/S[sec]) > 1? BEAMCHK_TAU/S[sec]:1
MON_RATE = MON_ANALOG? S[MON] : S[MON]/S[sec]
}
# FILT_MON_RATE = (FILT_MON_RATE*(nfilt-1) + MON_RATE)/nfilt
FILT_MON_RATE += MON_RATE/nfilt
relmonrate = MON_RATE? FILT_MON_RATE/MON_RATE : 0
if (relmonrate > 1) {
FILT_MON_RATE=MON_RATE
relmonrate = 1
}
if (!flag) {
if (set_sim(-1) || MON_RATE >= BEAMCHK_THRESH_HI) {
if (BEAMCHK_HI < 0)
BEAMCHK_THRESH_HI = -BEAMCHK_HI * FILT_MON_RATE
if (BEAMCHK_LO < 0)
BEAMCHK_THRESH_LO = -BEAMCHK_LO * FILT_MON_RATE
return(1)
} else {
printf("Beam down on %s\n", date())
printf("Waiting for beam ...\n")
BEAMCHK_FLAG = flag = 1
delay=time()
FILT_MON_RATE = 0
}
} else {
if (FILT_MON_RATE > BEAMCHK_THRESH_LO && relmonrate >= 1) {
tty_move(-1500, 1001)
tty_cntl("ce")
comment "Waited %d %s for beam." (time()-delay)/wtunit,wtunitl
flag = 0
user_chkbeam
} else {
wtime = time()-delay
if (wtime > 3600) {
wtunit = 3600; wtunitl = "hours"
} else if (wtime > 60) {
wtunit = 60; wtunitl = "minutes"
} else {
wtunit = 1; wtunitl = "seconds"
}
bmess = FILT_MON_RATE/BEAMCHK_THRESH_LO > 1 ? \
sprintf("beam back: %8.2f%%",100*relmonrate):"beam down"
tty_move(-1500, 1001)
printf("Been waiting %.2g %s for beam ... (%s)", \
wtime/wtunit,wtunitl, bmess)
tty_cntl("ce")
print
user_beambck
}
}
return(0)
}'
if (!(whatis("user_chkbeam") & 2)) rdef user_chkbeam ""
if (!(whatis("user_beambck") & 2)) rdef user_beambck ""
#%UU%
#%MDESC%
# Cancels the beam checking feature.%BR%
#
def offbeamchk '
BEAMCHK_ON = 0
cdef("_chk_beamc","","beam","delete")
print "Beam check is OFF."
'
#%UU% [<counting_interval> [<monitor_counts> ["analog"]]]
#%MDESC%
# Waits until the beam is back.
# This macro loops counting for <counting_interval> until the monitor
# counts stabilize near <monitor_counts> (the threshold is actually 10%% of
# this value).
#
def waitforbeam '{
global MON_ANALOG FILT_MON_RATE
local t m
if ($# > 3){
print "Usage: waitforbeam [counting_interval [monitor_counts [\"analog\"]]"
exit
}
t = ($# < 1)? getval("Counting time in seconds", COUNT): $1
m = ($# < 2)? getval(sprintf("Monitor counts in %g sec", t), \
0.1*FILT_MON_RATE): $2
MON_ANALOG = ($# < 3)? !yesno("Integrating monitor", !MON_ANALOG):("$3"=="analog")
print
if (MON < 0 || t == 0 || (MON_RATE=MON_ANALOG?m:m/t) <=0 || MON == sec) {
# rdef chk_beam "break" # not sure of changing this with cdef
cdef("_chk_beamc","","beam","delete")
FILT_MON_RATE = 0
print "ERROR: Beam check not activated. "
if (MON < 0 || MON == sec)
print "The monitor is not properly set up."
else
print "Input parameters are not valid."
exit
}
_onbeamchk
count t
}'
#%MACROS%
#%AUTHOR% P. Fajardo, (Original 6/94).
# $Revision: 4.2 $ / $Date: 2008/02/27 13:27:42 $
#%TOC%
|