#%TITLE% MACHINFO.MAC
#
#%NAME%
# Macros to access storage ring status information.
#
#%CATEGORY% X-ray beam, Accelerator
#
#%DESCRIPTION%
#
#This macro set allows you:
#%UL%
#%LI% Include machine information in the data file.
#%LI% Display machine information on the screen.
#%LI% Use a counter to know the electron current of the
# Storage Ring.
#%LI% Wait for the beam refill some seconds before the refill (michkon/off).
#%XUL%
#
#The %B%machine\0information%B% consists of:
#%UL%
#%LI% The electron current of the Storage Ring.
#%LI% The status of the automatic mode: activated ('ON'),
# or not activated ('OFF'). And time left in automatic mode.
#%LI% The state of the front end: 'OPEN', 'CLOSED' or 'ERROR'.
#%LI% Readout of frontend interlocks and UHV valve (if present)
#%LI% Time for next refill
#%LI% The last message from the Control Room
#%XUL%
#%BR%
#Once the %B%misetup%B% macro has been executed:
#%UL%
#%LI% The above listed information is included in the headers of each scan.
#%LI% It can be displayed on the screen by executing %B%machinfo%B%.
#%LI% A counter named 'srcur' can be defined, which will display the storage
# ring current. If an error happens, the counter is loaded with -1.
#%LI% A counter named 'sbcur' can be defined, which will display the single
# bunch current. If an error happens, the counter is loaded with -1.
#%XUL%
#%BR%
#%EXAMPLE%
#%B%misetup%B% %BR%
#%BR%
#These lines will be included in your scan header:
#%PRE%
# #UMI0 Current AM SH U42_Gap U42_Taper
# #UMI1 130.00 OFF FE Open 29.99 0.02
# #UMI2 Refill in 7457 sec, Message: 17/10/2025-05:34 END OF RUN 25-8.
#%PRE%
#The previous information is an example for an insertion device beamline
#and varies accordingly for a bending magnet beam
#%BR%
#Version: $Revision: 4.38 $
#%END%
##### January 2012 !!!!
# some info about what has been changed from the old machinfo.mac.
# The idea is to move everything concerning the frontend to the new tango server
# and keep the gap and taper servers the old taco way, where the beam lines have
# not moved to new tango servers.
#
# * extract all on BPMs. They are not used.
# * check_id is no longer used. Just load id.mac on ids. nothing on bms.
##### October 2019 - EBS
# Changed the tango host from orion to acs and new syntax domain/family/member
# For Frontend:
# Old was tango://orion:10000/fe/D/1
# New is tango://acs.esrf.fr:10000/fe/master/bm01
# For Insertion device control:
# Old was tango://orion:10000/id/id/1
# New is tango://acs.esrf.fr:10000/id/master/id01
# Author: Staffan Ohlsson
need spec_utils
need blmenu
lfile = sprintf("%s/local/spec/macros/%s", BLISSADM, "id.mac")
if (file_info(lfile)) {
need id.mac
}
if (!(whatis("__mi_debug") & 2)) rdef __mi_debug \'#$*\'
#%UU%
#%MDESC% toggle debug mode for the present macros.
def MI_debug '{
if ((whatis("__mi_debug") >> 16) <= 5) { # just a # sign -> off
rdef __mi_debug "eprint \"MI>>> \" "
eprint "MachInfo debug is ON"
} else {
rdef __mi_debug \'#$*\'
eprint "MachInfo debug is OFF"
}
}
'
if (!(whatis("idsetup") & 2)) { # create if inexistent
rdef idsetup \'#$*\'
}
# If ID_tango.mac is loaded afterwards, it should be overwritten. If it was
#loaded before, those lines should not redefine it!
if (!(whatis("__ID_isatango") & 2)) { # create if inexistent
rdef __ID_isatango() \'{ return "NO" }\'
}
# this should eventually move to FE_config or be called by that
#%UU%
#%MDESC%
# No arguments!%BR%
# Initializes parameters to access the information from the machine.
def misetup '{
# get rid of old variables and the old cdefs
minfounsetup
unglobal MI_ON MI_PAR MI_ERROR MI_XBPM1 __MI_XBPM2
unglobal MI_XPOS1 MI_XPOS2 MI_IDPOS
unglobal MI_CHK MI_CHKT MI_WAITT MI_WAITING
unglobal MI_LASTREAD MI_LASTSR MI_LASTSB MI_UPDATE_T
MI_FEDEV = "misetup: don`t use old macros!"
local oldmacs, aux[], mac, str, nb_param
nb_param = $#
oldmacs = "mi_checkid _mi_state _mibmread _mibpmread \
_mibmwrite _mibpmwrite _mibpmwrite _mibpmshow \
mi_getxbpm misetgapcounter mi_getcounts mi_getsbcounts"
split(oldmacs, aux)
for (mac in aux) {
if (whatis(aux[mac]) & 2) {
str = "undef " aux[mac]
eval(str)
}
}
local func, attr, what, __errstr
# I very much dislike that many variables. rather use an asso array
global __MI[] __MI_IDPOS[]
# From ${TANGO_HOME}/cclient/tango-common.c :
# static const char *anon_subnames_array296[] = {"ON", "OFF", "CLOSE", \
# "OPEN", "INSERT", "EXTRACT", "MOVING", "STANDBY", "FAULT", "WARMUP", \
# "RUNNING", "ALARM", "DISABLE", "UNKNOWN"};
# Looks like the order comes from there.
__MI["states"][2] = "CLOSE" # The Front End is closed
__MI["states"][3] = "OPEN" # The Front End is open
__MI["states"][10] = "RUNNING" # The Front End is open with automatic opening mode on
__MI["states"][8] = "FAULT" # Fault on Front End
__MI["states"][12] = "DISABLE" # No operation permission for the Front End
__MI["states"][13] = "UNKNOWN" # Communication error on Front End
# Issued by attribute "SR_Mode"
__MI["srmodes"][1] = "USM"
__MI["srmodes"][2] = "MDT"
__MI["srmodes"][3] = "Shutdown"
__MI["srmodes"][4] = "Safety Test"
__MI["srmodes"][5] = "ID Test"
# issued by "Mode" - Mode of the frontend:
__MI["modes"][0] = "No mode validated"
__MI["modes"][1] = "Injection"
__MI["modes"][2] = "Beam delivery"
__MI["machinehost"] = "acs.esrf.fr:10000"
__MI["lastread"] = 0
__MI["lastsr"] = -1
__MI["lastsb"] = -1
__MI["updatetime"] = 5
__MI["timeout"] = 15
if (SPECBL == "") {
tty_cntl("md")
local str
str = "FATAL: machinfo needs BL info in SPECBL variable."
str = str " Check with your SPEC admin!"
print str
tty_cntl("me")
exit
}
local type, aux[]
if(nb_param == 1){
__MI["par"]["BL"] = toupper("$1")
}
else{
__MI["par"]["BL"] = toupper(SPECBL)
}
printf("using %s as BL name\n", __MI["par"]["BL"])
split(__MI["par"]["BL"], aux, "D") # SPECBL is consistently Dxx or IDyy
type = aux[0] == "I" ? "ID" : "D"
# Check if ID or BM
if (type == "ID") {
__MI["hasid"] = 1
__MI["device"] = sprintf("//%s/fe/master/id%s", __MI["machinehost"], aux[1])
# find out, which ds type is used for undulators
rdef _miread \'\'
rdef _miwrite \'\'
rdef _mishow \'_miIDshow\'
} else {
__mi_debug "this is a bending magnet bl"
__MI["hasid"] = 0
__MI["device"] = sprintf("//%s/fe/master/bm%s", __MI["machinehost"], aux[1])
rdef idsetup \'#\$*\'
rdef _miread \'\'
rdef _miwrite \'\'
rdef _mishow \'\'
}
# check for UHV valve validity
local attr, addr
addr = __MI["device"]
attr = "UHV_Valve_State"
TANGO_ERR = "-1"
__MI["UHVValve"] = tango_get(addr, attr)
# in case of absence of that valve, we`ll get an exception
if (TANGO_ERR == "API_EmptyDeviceAttribute") { # no such attr
__MI["UHVValve"] = -1
}
mistart
__MI["lastread"] = 0
__MI["lastsr"] = -1
__MI["lastsb"] = -1
__MI["updatetime"] = 5
__MI["waiting"] = 0 # indicating if we have waited at the beams return
setup_tail("minfo")
if (whatis("blmenu") & 0x2){
blmenuadd("Machine Info in Spec file","MachInfo","mibody","_miblmenu_")
}
__MI["macfname"] = "machinfo.mac"
}
'
#%IU%
def minfounsetup '{
cdef("","","mi","delete")
cdef("","","srcur","delete")
cdef("","","sbcur","delete")
cdef("","","xbpm1x","delete")
cdef("","","xbpm2x","delete") # keep the following, to clean out
cdef("","","idgap1","delete") # old macros
cdef("","","idgap2","delete")
cdef("","","idgap3","delete")
unglobal __MI
}
'
#%IU%
#%MDESC%
# Adds machine info at the header of each scan
#
def mistart '{
__MI["on"] = 1
cdef("Fheader","mi_Fheader;","mach",0)
}
'
#%UU%
#%MDESC%
# After this command spec will not longer read the machine info
# and it will not be included in the scan header anymore.
# With %B%mistart%B% you can switch the reading on again.
#
def mistop '{
__MI["on"] = 0
cdef("","mach","delete")
}
'
#%UU%
#%MDESC%
# Display machine information on the SPEC screen
def machinfo 'mishow'
def mishow '{
if (__MI["par"]["BL"] == 0 || __MI["par"]["BL"] == "") {
print "You must run first \"misetup\" first"
exit
}
miread
if (!__MI["error"]) {
local FMT, remaining, s
FMT = "%30s %-30s\n"
print
printf(FMT, "Machine information", __MI["par"]["BL"])
print
printf(FMT, "Current :", sprintf("%.2f mA", __MI["par"]["CURR"]))
s = __MI["par"]["LifeTime"]
printf(FMT, "Lifetime :", sprintf("%d:%d", int(s / 3600), int((s % 3600) / 60)))
printf(FMT, "Sgl Bunch Cur :", sprintf("%.2f mA", __MI["par"]["SBCURR"]))
printf(FMT, "AutoMode :", sprintf("%s ", __MI["par"]["FEAUTO"]) )
printf(FMT, "Shutter :", sprintf("%s", __MI["par"]["SHUTTER"]))
_mishow
print
printf(FMT, "Ilocks :", sprintf("FE(%s) PSS(%s) EXP(%s)", \
__MI["par"]["FEILOCK"], __MI["par"]["PSSILOCK"], \
__MI["par"]["EXPILOCK"]))
printf(FMT, "", sprintf("HQPS(%s)", \
__MI["par"]["HQPSILOCK"]))
print
if (__MI["UHVValve"] != -1) {
printf(FMT, "UHV Valve :", __MI["par"]["UHVVALVE"])
}
s = __MI["par"]["REFILL"]
remaining = sprintf("%d:%02d", int(s / 3600), int((s % 3600) / 60))
printf(FMT, "Count down for refill :", __MI["par"]["REFILL"] ? \
remaining : "n.a.")
print
printf(FMT, "Operation Mode :", sprintf("%s", __MI["par"]["MODE"]))
printf(FMT, "Mode :", sprintf("%s", __MI["par"]["SRMODE"]))
printf(FMT, "FillMode :", sprintf("%s", __MI["par"]["FILLMODE"]))
printf(FMT, "Latest message :", sprintf("%s", __MI["par"]["MESS"]))
} else {
printf("\nError getting machine information\n")
}
}
'
def __mi_tango_catch_error '{
if (TANGO_ERR != "0") {
tty_cntl("md")
__errstr = __MI["macfname"] " - " func "- ERROR: " what "(" addr ", " attr ")"
__MI_error(__errstr)
__mi_debug TANGO_ERR
tty_cntl("me")
__MI["error"] = 1
} else {
__MI["error"] = 0
}
}
'
#%IU%(mesg)
#%MDESC% Attempts to write indentical error message only once in a while
def __MI_error(errstr) '{
global __MIERR[]
local expiry, now, str
str = "MI: " errstr
expiry = 5 # seconds before message is redisplayed
now = time()
if (errstr in __MIERR) {
if ((time() - __MIERR[errstr]) > expiry) {
__MIERR[errstr] = now
eprint(str)
}
} else {
__MIERR[errstr] = now
eprint(str)
}
local x
for (x in __MIERR) {
if ((time() - __MIERR[x]) > 20) {
delete __MIERR[x]
}
}
}
'
#%UU% <mode?>
#%MDESC%
# Reads information from machine FE tango DS (as of April 2012)
def miread '{
local addr, func, what, __tab[], x
func = "miread"
__MI["error"] = 1
addr = __MI["device"]
# __MI member # tango ds attribute to get
__tab["SHUTTER"] = "FE_State"
__tab["FEAUTO"] = "Automatic_Mode"
__tab["FEILOCK"] = "FE_Itlk_State"
__tab["PSSILOCK"] = "PSS_Itlk_State"
__tab["EXPILOCK"] = "EXP_Itlk_State"
__tab["HQPSILOCK"] = "HQPS_Itlk_State"
__tab["UHVVALVE"] = "UHV_Valve_State"
__tab["SRMODE"] = "SR_Mode"
__tab["CURR"] = "SR_Current"
__tab["SBCURR"] = "SR_Single_Bunch_Current"
__tab["REFILL"] = "SR_Refill_Countdown"
__tab["MESS"] = "SR_Operator_Mesg"
__tab["FILLMODE"] = "SR_Filling_Mode"
__tab["MODE"] = "Mode"
__tab["LifeTime"] = "SR_Lifetime"
what = "tango_get"
for (;__MI["error"];) {
local srmode, mode
for (x in __tab) {
if (x == "UHVVALVE" && ! __MI["hasid"]) {
continue
}
attr = __tab[x]
__MI["par"][x] = tango_get(addr, attr)
__mi_debug "__MI[\"par\"][" x "] = ", __MI["par"][x], TANGO_ERR
__mi_tango_catch_error
}
__MI["error"] = 0
__MI["par"]["FEAUTO"] = __MI["par"]["FEAUTO"] ? "ON":"OFF"
__MI["par"]["FEILOCK"] = __MI["par"]["FEILOCK"] ? "ACTIVE":"INACTIVE"
__MI["par"]["PSSILOCK"] = __MI["par"]["PSSILOCK"] ? "ACTIVE":"INACTIVE"
__MI["par"]["EXPILOCK"] = __MI["par"]["EXPILOCK"] ? "ACTIVE":"INACTIVE"
__MI["par"]["HQPSILOCK"]= __MI["par"]["HQPSILOCK"] ? "ACTIVE":"INACTIVE"
__MI["par"]["UHVVALVE"] = __MI["par"]["UHVVALVE"] ? "CLOSE":"OPEN"
srmode = __MI["par"]["SRMODE"]
__MI["par"]["SRMODE"] = __MI["srmodes"][srmode]
if (__MI["par"]["SRMODE"] == "") {
__MI["par"]["SRMODE"] = "UNKNOWN" srmode
}
mode = __MI["par"]["MODE"]
__MI["par"]["MODE"] = __MI["modes"][mode]
}
if (__MI["hasid"]) {
_miread
}
}
'
#%IU%
#%MDESC%
# Macro that formats information for including it in the scan headers.
def mi_Fheader '{
miread
if (!__MI["error"]) {
local titles values
_miwrite
if (___fe_filling_mode() == "1 bunch") {
titles = titles" SB_CURR"
values = sprintf("%s %7.3f",values,__MI["par"]["SBCURR"])
}
local FMT
printf ("#UMI0 Current AutoM Shutter %s\n", titles)
printf ("#UMI1 %7.2f %3s %11s %s\n", __MI["par"]["CURR"],\
__MI["par"]["FEAUTO"], __MI["par"]["SHUTTER"], values)
printf ("#UMI2 Refill in %d sec, Fill Mode: %s / Message: %s\n",\
__MI["par"]["REFILL"],__MI["par"]["FILLMODE"], __MI["par"]["MESS"])
} else {
printf("#UMI0 Error reading machine information\n")
}
}
'
# motor positions should be correct in the scan header
##%IU%
##%MDESC%
## scan header output for ID beamlines
#def _miIDwrite '{
# if (__MI["hasid"]) {
# local x
## sync # avoid any error messages in the spec file.
# for ( x = 0; x < MOTORS; x++) {
# if (motor_par(x, "device_id") != "ID") {
# continue # not an ID motor
# }
# if (motor_par(x, "disable")) {
# continue # motor is disabled
# }
# titles = sprintf("%s %9s", titles, motor_mne(x))
# values = sprintf("%s %9.4f", values, A[x])
# __mi_debug titles, values
# }
# }
#}
#'
#%IU%
#%MDESC%
# Screen formatting for ID beamlines.
def _miIDshow '{
if (__MI["hasid"]) {
getangles
local FMT, x, any, aux[]
FMT = "%30s %-30s\n"
print
for ( x = 0; x < MOTORS; x++) {
if (motor_par(x, "device_id") != "__ID") {
continue # not an ID motor
}
if (motor_par(x, "disable")) {
continue # motor is disabled
}
any += 1
aux[motor_mne(x)] = A[x]
}
if (any) {
printf(FMT, "Enabled insertion devices :", "Motors Positions")
for (x in aux) {
printf(FMT, sprintf("%s :", x), sprintf("%10g", aux[x]))
}
}
}
}
'
#%IU%
#%MDESC%
# Return positions as a formatted string.
# as demanded by ID1/2
def _miIDpositions() '{
if (__MI["hasid"]) {
getangles
local retstr, x, aux[]
print
for ( x = 0; x < MOTORS; x++) {
if (motor_par(x, "device_id") != "__ID") {
continue # not an ID motor
}
if (motor_par(x, "disable")) {
continue # motor is disabled
}
retstr = retstr sprintf("%s=%05.2fmm,", motor_mne(x), A[x])
}
return retstr
}
}
'
#%IU%
#%MDESC%
# macro to include start/stop on blmenu
def mibody(mode) '{
if (mode==1) {
if (__MI["on"]) {
mistop
} else {
mistart
}
}
if (mode==2) {
machinfo
}
return(sprintf("%s", __MI["on"]?"Active":"Not active"))
}
'
#%UU% [<refill-time>] [<waittime>]
#%MDESC%
# Activates refill feature on chk_beam.
# <refill-time> is the time before a refill whithin scans will wait for refill
# if no parameter is given, a default of 15 seconds is set. Minimum value is
# 10 seconds.
# <waittime> is the time to wait once the beam is back. Allows to wait for the
# undulators to close, optic to heat up ...
def michkon '{
if (__MI["par"]["BL"] == 0 || __MI["par"]["BL"] == "") {
print "michkon: You must run first \"misetup\" first"
exit
}
if ($# < 1) {
__MI["checktime"] = 15
__MI["waittime"] = 15
} else if ($# == 1) {
__MI["checktime"] = $1
__MI["waittime"] = 15
} else if ($# == 2) {
__MI["checktime"] = $1
__MI["waittime"] = $2
}
__MI["check"] = 1
cdef("measure0", "mi_measure0;","_chkb_")
}
'
#%UU%
#%MDESC
# Deactivates refill feature on chk_beam
# previously activated by michkon
def michkoff '{
__MI["check"] = 0
cdef("","","_chkb_","delete")
}
'
######################################################################
########################### ###########################
########################### FE BEHAVIOUR ###########################
########################### ###########################
######################################################################
#%UU%
#%MDESC
# Enables the automatic mode : FE will automatically re-open after a
# refill.
def mi_set_automatic_mode()'{
local macro, func, addr, cmd, what, __errstr
func = "mi_set_automatic_mode()"
attr = "Automatic"
what = "tango_io"
addr = __MI["device"]
tango_io(addr, attr)
__mi_tango_catch_error
}
'
######################################################################
#################### ####################
#################### MACHINE PARAMETERS READING ####################
#################### ####################
######################################################################
#%IU% ()
#%MDESC%
# Returns the remaining time to refill.
def mi_refilltime() '{
local macro, func, attr, what, addr, __errstr, remaint, srmode
func = "mi_refilltime()"
attr = "SR_Mode"
what = "tango_get"
addr = __MI["device"]
srmode = tango_get(addr, attr)
__mi_tango_catch_error
if (__MI["srmodes"][srmode] != "USM") { # nothing further to do
return -1
}
attr = "SR_Refill_Countdown"
remaint = tango_get(addr, attr)
__mi_tango_catch_error
return remaint
}
'
#%UU% ()
#%MDESC%
# Returns the synchrotron ring current in mA.
def mi_SR_Current() '{
local macro, func, attr, what, addr, __errstr, _attr_value, srmode
func = "mi_SR_Current()"
attr = "SR_Mode"
what = "tango_get"
addr = __MI["device"]
srmode = tango_get(addr, attr)
__mi_tango_catch_error
if (__MI["srmodes"][srmode] != "USM") {
# nothing further to do
return -1
}
attr = "SR_Current"
__mi_debug "attr=" attr
__mi_debug "addr=" addr
_attr_value = tango_get(addr, attr)
__mi_tango_catch_error
return _attr_value
}
'
#%UU% ()
#%MDESC%
# Returns the synchrotron ring current in mA. (fast but less safe version)
def mi_SR_Current_fast() '{
return tango_get(__MI["device"], "SR_Current")
}'
#%IU% ()
#%MDESC%
# Returns the operator message.
def mi_message() '{
local func, attr, what, addr, msg
func = "mi_message()"
attr = "SR_Operator_Mesg"
what = "tango_get"
addr = __MI["device"]
msg = tango_get(addr, attr)
__mi_tango_catch_error
return msg
}
'
#%UU% ()
#%MDESC%
# Returns the front end state as a string
def mi_festate() '{
return ___fe_state()
}'
#%UU% ()
#%MDESC%
# Returns non zero if PSS interlock is active
def mi_intlck_pss() '{
local func, attr, what, addr, msg
func = "mi_intlck_pss()"
attr = "PSS_Itlk_State"
what = "tango_get"
addr = __MI["device"]
msg = tango_get(addr, attr)
__mi_tango_catch_error
return msg
}'
#%UU% ()
#%MDESC%
# Returns non zero if EXP interlock is active
def mi_intlck_exp() '{
local func, attr, what, addr, msg
func = "mi_intlck_exp()"
attr = "EXP_Itlk_State"
what = "tango_get"
addr = __MI["device"]
msg = tango_get(addr, attr)
__mi_tango_catch_error
return msg
}'
#%UU% ()
#%MDESC%
# Returns non zero if FE interlock is active
def mi_intlck_fe() '{
local func, attr, what, addr, msg
func = "mi_intlck_fe()"
attr = "FE_Itlk_State"
what = "tango_get"
addr = __MI["device"]
msg = tango_get(addr, attr)
__mi_tango_catch_error
return msg
}'
#%UU% ()
#%MDESC%
# Returns non zero if HQPS interlock is active
def mi_intlck_hqps() '{
local func, attr, what, addr, msg
func = "mi_intlck_hqps()"
attr = "HQPS_Itlk_State"
what = "tango_get"
addr = __MI["device"]
msg = tango_get(addr, attr)
__mi_tango_catch_error
return msg
}'
#%UU% ()
#%MDESC%
# Returns non zero if automatic front end mode is on
def mi_automode() '{
local func, attr, what, addr, msg
func = "mi_automode()"
attr = "Automatic_Mode"
what = "tango_get"
addr = __MI["device"]
msg = tango_get(addr, attr)
__mi_tango_catch_error
return msg
}'
#%UU% ()
#%MDESC%
# Returns the remaining time for automatic front end mode
def mi_autotime() '{
return "autotime no more available"
}'
#%UU% ()
#%MDESC%
# Returns the remaining time for automatic front end mode
def mi_autotime_str() '{
return "autotime str no more available"
}'
#%IU% ()
#%MDESC%
# Returns the lifetime.
def mi_lifetime() '{
local func, attr, what, addr, lifet
func = "mi_lifetime()"
attr = "SR_Lifetime"
what = "tango_get"
addr = __MI["device"]
lifet = tango_get(addr, attr)
__mi_tango_catch_error
return lifet
}
'
#%IU% ()
#%MDESC%
# Returns the operation mode as text: No mode validated, Injection, Beam Delivery
def mi_mode() '{
local func, attr, what, addr, value
func = "mi_mode()"
attr = "Mode"
what = "tango_get"
addr = __MI["device"]
value = tango_get(addr, attr)
__mi_tango_catch_error
return __MI["modes"][value]
}
'
#%IU% ()
#%MDESC%
# Returns the mode as text: USM, MDT etc.
def mi_srmode() '{
local func, attr, what, addr, value
func = "mi_srmode()"
attr = "SR_Mode"
what = "tango_get"
addr = __MI["device"]
value = tango_get(addr, attr)
__mi_tango_catch_error
return __MI["srmodes"][value]
}
'
#%IU% (<flag>)
#%MDESC% Check if the accelerator filling mode.
def ___fe_filling_mode() '{
local func, attr, what, addr, __errstr, fefm
func = "___fe_filling_mode"
addr = __MI["device"]
attr = "SR_Filling_Mode"
what = "tango_get"
fefm = tango_get(addr, attr)
__mi_tango_catch_error
return fefm
}
'
######################################################################
############################ ############################
############################ CHECK BEAM ############################
############################ ############################
######################################################################
#%IU%
#%MDESC
# chk_beam stuff
def mi_chkbeam '{
local refill
if (__MI["check"]) {
refill = mi_refilltime()
if (refill != -1) {
if (refill < __MI["checktime"]) {
printf("Waiting for Beam refilling (%d sec left)\r",refill)
__MI["waiting"] = __MI["waittime"] # waiting needed
sleep(1)
return(0)
}
else if (__MI["waiting"] > 0) {
printf("Waiting after Beam is back (%d sec left)\r",__MI["waiting"])
__MI["waiting"] -= 5 # doing waiting
sleep(5)
return(0)
}
}
}
}
'
#%UU% [<check_time> [<wait_time>]]
#%MDESC%
# waitforreffill can be used directly without a parameter,
# behaviour will then depend on previous michkon / michkoff.
# With a parameter, on/off is ignored and the wait is done with the
# value in the first argument. An additional parameter can be used to
# wait for <wait_time> seconds after beam is back (Ex: to wait for
# heating or end of cleanup).
def waitforrefill '{
local check_time wait_time
local nvals vals
local do_stabilization_wait sleep_time refill_duration
local already_waiting
already_waiting = 0
if ($# > 0 ) {
check_time = $1
if ($# > 1){
wait_time = $2
}
}
else {
if (__MI["check"]) {
check_time = __MI["checktime"]
}
else {
check_time = -1
}
if (__MI["waiting"]) {
wait_time = __MI["waiting"]
}
else {
wait_time = -1
}
}
sleep_time = 5
do_stabilization_wait = 0
refill = mi_refilltime()
refill_duration = 0
# printf("WFR: checktime=%g waittime=%g refill=%g\n", check_time, wait_time, refill)
while (refill < check_time) {
# A refill will occur before check_time seconds.
if (already_waiting == 0){
already_waiting = 1
user_wfr_enter_wait
}
refill = mi_refilltime()
if ( (refill == -1) && (__MI["error"] == 0) ) {
# MDT or ShutDown => do not wait.
break
}
if(refill > 1){
printf("Waiting for Beam refilling (%d sec left) (%gs requiered)\r", refill, check_time)
}
else{
printf("Waiting for end of refill (for %ds) \r", refill_duration)
sleep_time = 1 # to reduce useless overhead.
refill_duration += sleep_time
}
sleep(sleep_time)
do_stabilization_wait = 1
}
if(do_stabilization_wait && wait_time){
printf("Beam is back ! Now waiting stabilization for %d seconds...\n", wait_time)
countdown(wait_time)
}
already_waiting = 0
user_wfr_exit_wait
}'
cdef("user_wfr_enter_wait", "#$*\n", "_wfr_")
cdef("user_wfr_exit_wait", "#$*\n", "_wfr_")
#%UU%
#%MDESC%
# Waits machine not to be in Injection mode and frontend open.
def wait_for_beam '{
local beam_status front_end_status
beam_status = mi_mode()
front_end_status=___fe_state()
while (beam_status == "Injection") {
print "wait_for_beam : still in injection, checking every minute"
sleep(60)
beam_status = mi_mode()
}
if (beam_status == "Beam delivery") {
print "wait_for_beam : beam is on, ckecking for front end status"
front_end_status = ___fe_state()
while (front_end_status == "FE closed") {
print "wait_for_beam : front end closed, trying to open it every minute"
feopen
sleep(60)
front_end_status = ___fe_state()
}
print "wait_for_beam : front end is open, the experiment can continue"
}
}'
cdef("user_michk_prewait", "#$*\n", "_michk_")
cdef("user_michk_postwait", "#$*\n", "_michk_")
#%IU%
#%MDESC%
# mi_measure0 replaces mi_chkbeam.
# It loops until refill is finished. This is done without counting
# which avoids to trig counting cards and detectors.
def mi_measure0 '{
local chkt, refill, iwaswaiting, prstr, srmode, prewaitcalled
__MI["waiting"] = 0
iwaswaiting = 0
prewaitcalled = 0
# Save the srmode at the beginning of the scan
if ( NPTS == 0 ) {
__MI["saved_srmode"] = mi_srmode()
}
# Reads time to refill. (ttr)
refill = mi_refilltime()
# last counting time + security time set by user.
chkt = _ctime + __MI["checktime"]
__mi_debug "refill", refill, "chkt", chkt, (refill < chkt)
while (refill < chkt) {
"""
HW: 2013/3/18
check the SR mode at the start and the current one:
* If they are the same, but it`s not USM, then the scan was started outside user mode. Thus
is can run.
* If they are different and the current mode is NOT user mode, then we went from USM to to
MDT or Shutdown, in which case the scan should be suspended, the moment it changes.
* Obviously, when neither is true, we need to proceed to the loop, which awaits the return
of the beam after an injection.
hope that works!
"""
srmode = mi_srmode()
if ((srmode == __MI["saved_srmode"]) && \
(srmode != "USM")) {
# not in user mode, break loop.
break
} else
if ((srmode != __MI["saved_srmode"]) && \
(__MI["saved_srmode"] == "USM")) {
# changed from USM to MDT/Shutdown, suspend scan.
prstr = ": SR mode is " srmode
} else
{
# Injection during USM, suspend scan until beam comes back
prstr = " - " refill > 0 ? refill : 0 " sec left "
}
printf("Waiting for Beam%s\r", prstr)
__MI["waiting"] = __MI["waittime"] # Waiting needed after the beam return.
if (!prewaitcalled) {
user_michk_prewait
prewaitcalled = 1
}
sleep(2)
refill = mi_refilltime()
}
if (__MI["waiting"] > 0) {
print
}
while(__MI["waiting"] > 0) {
__mi_debug "__MI[\"waiting\"] > 0"
iwaswaiting = 1
printf("Waiting after Beam is back (%d sec left)\r", __MI["waiting"])
__MI["waiting"] -= 5
# doing waiting
sleep(5)
}
if (prewaitcalled) {
user_michk_postwait
}
if (iwaswaiting) {
print "\nBeam is back. Scan resumed."
}
}
'
#%UU%
#%MDESC%
# Open the frontend shutter from SPEC
#
def feopen '{
___feopen
}'
#%IU%
#%MDESC%
# Open the frontend shutter from SPEC
#
def ___feopen '{
if (!__MI["device"]) {
eprintf("Don`t forget to run ")
tty_cntl("md"); print "misetup"; tty_cntl("me")
exit
}
local func, attr, what, addr, __errstr
func = "feopen"
addr = __MI["device"]
attr = "Open"
what = "tango_io"
tango_io(addr, attr)
__mi_tango_catch_error
___fe_pollfe("open")
}
'
#%UU%
#%MDESC%
# Close the frontend shutter from SPEC
#
def feclose '{
if (!__MI["device"]) {
eprintf("Don`t forget to run ")
tty_cntl("md"); print "misetup"; tty_cntl("me")
exit
}
local func, attr, what, addr, __errstr
func = "feclose"
addr = __MI["device"]
attr = "Close"
what = "tango_io"
tango_io(addr, attr)
__mi_tango_catch_error
___fe_pollfe("close")
}
'
def idopen 'print "Please use feopen!"; feopen'
def idclose 'print "Please use feclose!"; feclose'
#%IU% ()
#%MDESC%
def ___fe_state() '{
local func, attr, what, addr, __errstr, festate
func = "___fe_state"
addr = __MI["device"]
attr = "FE_State"
what = "tango_get"
if (!addr) {
return -1
}
festate = tango_get(addr, attr)
__mi_tango_catch_error
return festate
}
'
#%IU% (<what>)
#%MDESC%
# Some complementary info:%BR%
# Attribute FE_State can deliver the following answers:%BR%
#"FE open", "FE closed", "FE fault", "FE disabled", "FE unknown"
def ___fe_pollfe(what) '{
local festate st_time festate
st_time = time()
for(;;) {
festate = ___fe_state() # string like "FE Open"
if (festate == "FE closed") {
# FE closed
if ( what == "close" ) {
return(0)
}
}
else if (festate == "FE open") {
# FE open
if ( what == "open" ) {
return(0)
}
}
else {
printf("Problem with frontend command \"%s\". festate is: ", what)
tty_cntl("md"); printf("%s\r", festate); tty_cntl("me")
}
sleep(0.2)
if ((time() - st_time) > __MI["timeout"]) {
printf("\nTimeout polling on frontend. Giving up.\n")
return(-1)
}
}
}
'
#%IU% (<what>)
#%MDESC% <what> : state in {"close"; "open"}%BR%
# macro to replace possibly needed macro from the old id.mac
def id_pollfe(what) '{
return ___fe_pollfe(what)
}
'
#%IU% (<flag>)
#%MDESC% Check if the front end is open. Open it if %B%flag%B% set.
def ___fe_check(flag) '{
local stat
stat = ___fe_state()
if (flag == 0) {
if (stat != "FE open"){
eprintf ("Front End not open, exiting...\n")
return (-1)
}
}
else if (stat == "FE closed"){
feopen
}
return(stat)
}
'
#%IU% (<flag>)
#%MDESC% VINTAGE function to check if the front end is open. Open it if
# %B%flag%B% set.
#%BR%Only this old version is being used in other macros and they expect a
# numeric value to be returned according to the old taco DS.
#%BR%Old state values of the frontend were: 0 (unknown), 3 (close), 4(open),
# 17 (automatic), 23 (fault), 46 (disabled) or -1 iferror.
def _check_fe(flag) '{
local stat
stat = ___fe_check(flag)
if (stat == "FE open") {
return 4
}
else if (stat == "FE closed") {
return 3
}
else if (stat == "FE fault") {
return 23
}
else if (stat == "FE disabled") {
return 46
}
else {
return 0
}
}
'
###################################################################################
#
# Macro Counter macros, used for reading Storage Ring and Single Bunch currents
#
###################################################################################
#%IU%(cnum, type, unit, mod, chan)
#%MDESC%
#%BR% %BR%Declare a %B%counter\0controller%B%:
#%BR% %BR%
#%PRE%
#SCALERS\0\0\0DEVICE\0\0\0ADDR\0\0\0\0\0\0\0<>MODE\0\0NUM\0\0\0\0\0\0\0\0\0\0\0\0<>TYPE
#\0\0\0\0YES\0\0\0\0SRCUR\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\02\0\0\0\0\0Macro\0Counter
#%PRE%
# No address is necessary, as it will be taken from misetup.
#%BR% %BR%
#Then create %B%macro\0counters%B% in a similar manner:
#%BR% %BR%Unit is index num of controller, channel 0 is for the storage ring current, 1 for single bunch current.%BR%
#Number\0\0\0Name\0\0Mnemonic\0\0\0Device\0\0Unit\0\0Chan\0\0\0<>Use\0As\0\0Scale\0Factor
#\0\0\0\0\03\0\0srcur\0\0\0\0\0srcur\0\0MAC_CNT\0\0\0\0\02\0\0\0\0\00\0\0\0\0counter\0\0\0\0\0\0\0\0\0\0\0\0\01
#\0\0\0\0\04\0\0sbcur\0\0\0\0\0sbcur\0\0MAC_CNT\0\0\0\0\02\0\0\0\0\01\0\0\0\0counter\0\0\0\0\0\0\0\0\0\0\0\0\01
# %BR%Called by spec
# %BR%
#Note: the internal variable SRCUR_addr will not be used. Please use misetup.
def SRCUR_config(cnum, type, unit, mod, chan) '{
# chan will be used for counters to designate the tag address. Leave alone.
__mi_debug "Configuring SRCUR", cnum, type, unit, mod, chan
__mi_debug "No action here!"
if (type == "ctrl") {
if (!__MI["device"]) {
eprintf("Don`t forget to run ")
tty_cntl("md"); print "misetup"; tty_cntl("me")
__MI["device"] = SRCUR_ADDR
}
}
}
'
#%IU%(cnum, attr, p1, p2, p3)
#%MDESC% Channel 0 will return the SR current and channel 1 the single bunch
# current.%BR%
# Called by spec%BR%
#Note: the internal variable SRCUR_addr will not be used. Please use misetup.
#%END%
# I`d like to check the mode to find out about the validity of the single bunch
# current, but that`s not yet possible.
#%BR%From the file
#/segfs/tango/cppserver/machine/machstat_wrapper/MachStatWrapClass.cpp
# we get the possible SR filling modes:%BR%
# vect_data.push_back("uniform multibunch");%BR%
# vect_data.push_back("1/3 multibunch");%BR%
# vect_data.push_back("2/3 multibunch");%BR%
# vect_data.push_back("2*1/3 multibunch");%BR%
# vect_data.push_back("7/8 multibunch");%BR%
# vect_data.push_back("1 bunch");%BR%
# vect_data.push_back("4 bunch");%BR%
# vect_data.push_back("16 bunch");%BR%
# vect_data.push_back("32 bunch");%BR%
# vect_data.push_back("24*8+1bunch");%BR%
# vect_data.push_back("4GeV");%BR%
# vect_data.push_back("5GeV");%BR%
# vect_data.push_back("Empty");%BR%
# There is a single bunch current in several modes. Don't bother right now.
def SRCUR_cmd(cnum, cmd, p1, p2, p3) '{
local unit, chan, retval, attr
__mi_debug "Command SRCUR", cnum, cmd, p1, p2, p3
if (cnum != "..") {
if (cmd == "counts") {
channel = counter_par(cnum, "channel")
local func, attr, what, addr, __errstr, srmode
func = "SRCUR_cmd"
what = "tango_get"
addr = __MI["device"]
if (channel == 0) {
attr= "SR_Current"
if (!__MI["device"]) {
eprintf("\nPlease run ")
tty_cntl("md"); print "misetup"; tty_cntl("me")
}
}
else if (channel == 1) {
attr= "SR_Single_Bunch_Current"
}
else if (channel == 2) {
attr= "SR_Refill_Countdown"
}
else if (channel == 3) {
attr= "SR_Mode"
}
if (!__MI["device"]) {
return (1e1000/1e1000)
}
what = "tango_get"
__mi_debug what "(" addr "," attr ")"
TANGO_ERR = "-1"
retval = tango_get(addr, attr)
# do not pick up errors, as we will just return the -1 resulting from
# the tango_get call, if we`re not in USM, Then the server will set the
# quality of the attr to INVALID and spec gives an error. --> return -1
#__mi_tango_catch_error
# return count
return(retval)
}
}
# else {
# if (!__MI["device"]) {
# eprintf("Please run ")
# tty_cntl("md"); print "misetup"; tty_cntl("me")
# }
# }
}
'
#%IU%
#%MDESC%
# Reading insertion devices from the old taco servers.
def _miidread '{
if (__MI["hasid"]) {
ESRF_ERR = -1
if (esrf_io(IDDEV, "DevRead", __MI_IDPOS) == -1) {
__MI["error"] = 1
}
}
}
'
#%IU%
#%MDESC%
# scan header output with the old taco servers.
def _miidwrite '{
if (__MI["hasid"]) {
local naxis ax name
naxis = list_n(IDAXIS)
for (ax=0;ax<naxis;ax++) {
name = list_getpar(IDAXIS,sprintf("_%d",ax+1),"meca")
titles = sprintf("%s %s_Gap %s_Taper",titles,name,name)
values = sprintf("%s %9.4f %9.4f",values,__MI_IDPOS[ax*2],__MI_IDPOS[ax*2+1])
}
}
}
'
#%IU%
#%MDESC%
# Screen formatting for the old taco servers.
def _miidshow '{
if (__MI["hasid"]) {
local naxis ax name, FMT
FMT = "%30s %-30s\n"
naxis = list_n(IDAXIS)
if (naxis > 0) {
print
printf(FMT, "ID :", sprintf("%10s %10s", "Gap(mm)", "Taper(mm)"))
}
for (ax=0;ax<naxis;ax++) {
name = list_getpar(IDAXIS,sprintf("_%d",ax+1),"meca")
printf(FMT, sprintf("%s :", name), sprintf("%9.4g %9.4g",__MI_IDPOS[ax*2],__MI_IDPOS[ax*2+1]))
}
} else {
print
printf(" ID (not avail. id.mac needed)\n")
}
}
'
#%IU%()
#%MDESC%Get state of all undulators%BR%
# function which copies behaviour of the old id_state() from the old id.mac
#%BR% Return the state of the frontend -> 0 (unknown), 3 (close), 4(open),
#17 (automatic), 23 (fault), 46 (disabled) or -1 iferror.
def id_state() '{
__mi_debug "id_state"
local state
if ((state = ___fe_state()) == -1 ) {
local func, attr, what, __errstr
func = "id_state()"
__errstr = __MI["macfname"] " - " func " - ERROR\n"
__MI_error(__errstr)
return(-1)
}
else {
if (state == "FE closed") {
return 3
}
else if (state == "FE open") {
return 4
}
else if (state == "FE fault") {
return -1
}
else if (state == "FE disabled") {
return 46
}
else if (state == "FE unknown") {
return 0
}
}
}
'
###################################################################################
#
# Macro Counter enable/disable
#
###################################################################################
#%UU%
#%MDESC%Disable all storage ring counters.%BR%
def mioff '{
local cnt
for(cnt=0; cnt < COUNTERS; cnt++) {
if (counter_par(cnt, "device_id") == "SRCUR") {
counter_par(cnt, "disable", 1)
}
}
}
'
#%UU%
#%MDESC%Enable all storage ring counters.%BR%
def mion '{
local cnt
for(cnt=0; cnt < COUNTERS; cnt++) {
if (counter_par(cnt, "device_id") == "SRCUR") {
counter_par(cnt, "disable", 0)
}
}
}
'
######################################################################
######################### ########################
######################### MACHINE MODE INFO ########################
######################### ########################
######################################################################
def mi_get_mode() '{
local attr, addr
addr = "//acs.esrf.fr:10000/sys/machstat/tango"
attr = "Sr_mode"
# SR Mode
# 1 /* USM */
# 2 /* MDT */
# 3 /* SHUTDOWN */
# 4 /* SAFETY TEST*/
# 5 /* ID TEST*/
# Il y a aussi tous les parametres machines importants: (courant,
# lifetime, countdown, message operatoro, état des frontends...
TANGO_ERR = "-1"
_mode = tango_get(addr, attr)
if (TANGO_ERR == "API_EmptyDeviceAttribute") {
# no such attr
_mode = -1
}
return _mode
}'
def mi_mode_is_USM() '{
return mi_get_mode() == 1
}'
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# Functions here might use functions from ID_tango.mac
#%AUTHOR%
# MACHINFO.MAC - HW, Jan 2012
#%END%
# $Revision: 4.38 $ / $Date: 2023/08/29 07:54:12 $
#%TOC%
|