#%TITLE% MONOCHK.MAC
#%NAME%
# Checks monochromator tuning and machine current intensity during scans.
#
#%CATEGORY% Tools
#
#%DESCRIPTION%
# When activated (%B%onmonochk%B%), the mono intensity is monitored and if it goes down below a certain threshold, the on-going scan stops temporarily while a "ghost" scan (line up scan of %B%ghscans.mac%B%) re-align the mono on its maximum of intensity. After what the previous ongoing scan resumes. If it appears that the mono intensity loss is due to a beam loss, the on-going scan stops as well and SPEC waits for the beam is back before realigning the mono and continuing the scan.
#%SETUP%
#It is possible to adapt the feature to particular needs, by defining 3 user macros :
#%DL%
#%DT%user_scan_mono%DD% called before each ghost line up scan of the mono when the %B%_monochk()%B% has detected it needs to be re-aligned. ("return 0" to skip the line-up and return to %B%chk_beam%B% directly.)
#%DT%user_lineup%DD% called after each re-alignement of the mono.
#%DT%user_beam_is_back%DD% called after beam recovery and before pre-scanning the mono. ("return 1" to skip the pre-scan and return to %B%chk_beam%B% directly.)
#%XDL%
#
#%END%
#%UU% [mon] [mthr] [time] [io] [iothr] [mot] [max] [mag] [steps] [plot] [sleep] [time2] [mag2] [steps2]
#%MDESC% macros initialisation and parameters setting.%BR%
# %PRE%
#[mon] : mnemonic of the counter that monitors the mono intensity.
#[mthr] : mono intensity high threshold in percent of maximum of intensity.
#[time] : integration time for measuring the intensity and scanning the mono.
#[io] : mnemonic of the counter that monitors the machine current.
#[iothr]: machine current low threshold in percent of normal current.
#[mot] : mnemonic of the monochromator motor to be lined up.
#[max] : "CEN|COM|PK" line up at what is specified (PK means max of peak).
#[mag] : line up scan magnitude.
#[steps]: line up scan number of intervals.
#[plot] : line up scan plot filter number.
#[sleep]: stabilization time after beam is back.
#[TIME2]: integration time for pre-scanning the mono (after beam is back).
#[MAG2] : pre-scan magnitude.
#[STEPS2]:pre-scan number of intervals.
# %PRE%
# If no mnemonic is specified as machine current monitor, the "beam check" activity is disabled. If no motor or no monochromatic beam monitor are specified, the "mono check" activity cannot be activated.
global MCK_LOG
MCK_LOG=1
def monochksetup '{
global MCK_SCANNINGMONO MCK_WAITINGFORBEAM MCK_MONO_ITER MCK_WAITDELAY
global MCK_RATE MCK_BRATE MCK_THRESHOLD MCK_BEAMTHRESHOLD
global MCK_ANALOG MCK_BANALOG MCK_ON
global MCK_PAR MCK_SETUP_OK
cdef ("config_mac","_monochk_chkpar;_monochk_defmac;","monochk")
cdef ("user_cleanup2","_monochk_cleanup;","monochk")
cdef ("user_getcounts","_monochk_threshold;","monochk",0x20)
if (!(whatis("__monochk_ghopt")&2)) rdef __monochk_ghopt ""
if (!(whatis("user_scan_mono")&2)) rdef user_scan_mono \'#\$*\'
if (!(whatis("user_beam_is_back")&2)) rdef user_beam_is_back \'#\$*\'
# if (!(whatis("user_end_monochk")&2)) rdef user_end_monochk \'#\$*\'
setup_tail("monochk")
if ($#) {
MCK_PAR["MON"] = "$1"
MCK_PAR["MTHR"] = $2
MCK_PAR["TIME"] = $3
MCK_PAR["IO"] = "$4"
MCK_PAR["IOTHR"] = $5
MCK_PAR["MOT"] = "$6"
MCK_PAR["MAX"] = "$7"
MCK_PAR["MAG"] = $8
MCK_PAR["STEPS"] = $9
MCK_PAR["PLOT"] = $10
MCK_PAR["SLEEP"] = $11
MCK_PAR["TIME2"] = $12
MCK_PAR["MAG2"] = $13
MCK_PAR["STEPS2"] = $14
_monochk_chkpar
_monochk_defmac
} else {
menu("MONO CHECK SETUP","_monochk_menu","_monochk_chkpar","_monochk_defmac")
}
}
__monochk_ghopt
'
#%IU%
#%MDESC% %B%setup%B% service. Gets rid of %B%monochk%B% software.
def monochkunsetup '{
offmonochk
cdef ("","","monochk","delete")
}'
#%IU%
#%MDESC% Sets default values and checks all the parameters are properly set to allow "mono check" feature activation or not.
def _monochk_chkpar '{
local aa
MCK_SETUP_OK=1
if (-1!=(aa=cnt_num(MCK_PAR["MON"]))) MON = aa
else {
if (MCK_PAR["MON"])\
menuerror (sprintf("%s not a configured counter",MCK_PAR["MON"]))
if (MON>=0) MCK_PAR["MON"] = cnt_mne(MON)
else {
MCK_PAR["MON"] = ""
MCK_SETUP_OK=0
}
}
if (MCK_PAR["IO"] && -1==cnt_num(MCK_PAR["IO"])) {
menuerror (sprintf("%s not a configured counter",MCK_PAR["IO"]))
MCK_PAR["IO"] = ""
}
if (MCK_PAR["MOT"] && -1==motor_num(MCK_PAR["MOT"])) {
menuerror (sprintf("%s not a configured motor",MCK_PAR["MOT"]))
MCK_PAR["MOT"] = ""
MCK_SETUP_OK=0
}
MCK_PAR["MTHR"] = MCK_PAR["MTHR"]>0 ? MCK_PAR["MTHR"] : 80
MCK_PAR["IOTHR"] = MCK_PAR["IOTHR"]>0 ? MCK_PAR["IOTHR"] : 10
MCK_PAR["PLOT"] = MCK_PAR["PLOT"] ? MCK_PAR["PLOT"] : 2
MCK_PAR["STEPS"] = MCK_PAR["STEPS"] ? MCK_PAR["STEPS"] : 1
MCK_PAR["TIME"] = MCK_PAR["TIME"] ? MCK_PAR["TIME"] : 1
MCK_PAR["TIME2"] = MCK_PAR["TIME2"] ? MCK_PAR["TIME2"] : MCK_PAR["TIME"]
MCK_PAR["MAG2"] = MCK_PAR["MAG2"] ? MCK_PAR["MAG2"] : MCK_PAR["MAG"]*10
MCK_PAR["STEPS2"] = MCK_PAR["STEPS2"] ? MCK_PAR["STEPS2"] : MCK_PAR["STEPS"]
if (MCK_PAR["MAX"]!="CEN" && MCK_PAR["MAX"]!="COM") MCK_PAR["MAX"] = "PK"
}'
#%IU%
#%MDESC% Defines internal macros from the setup parameters.
def _monochk_defmac '{
local macro
if (MCK_ON && !MCK_SETUP_OK) {
offmonochk
}
macro = ""
macro = macro "ghlineup "
macro = macro MCK_PAR["MOT"] " -MCK_PAR[\"MAG\"] MCK_PAR[\"MAG\"]"
macro = macro " MCK_PAR[\"STEPS\"] MCK_PAR[\"TIME2\"] -MCK_THRESHOLD*0.8\n"
macro = macro "user_lineup " MCK_PAR["MOT"] "\n"
macro = macro "printf(\"" MCK_PAR["MOT"] " re-tuned at %g degrees\\n\""
macro = macro ",A[" MCK_PAR["MOT"] "])\n"
rdef __scan_mono macro
macro = ""
macro = macro "ghlineup "
macro = macro MCK_PAR["MOT"] " -MCK_PAR[\"MAG2\"] MCK_PAR[\"MAG2\"]"
macro = macro " MCK_PAR[\"STEPS2\"] MCK_PAR[\"TIME2\"] -MCK_THRESHOLD*0.8\n"
macro = macro "user_lineup " MCK_PAR["MOT"] "\n"
macro = macro "printf(\"" MCK_PAR["MOT"] " pre-tuned at %g degrees\\n\""
macro = macro ",A[" MCK_PAR["MOT"] "])\n"
rdef __prescan_mono macro
macro = sprintf("ghopt peak=%s title=mono_correction plot=%d counters=%s\n" ,MCK_PAR["MAX"],MCK_PAR["PLOT"],MCK_PAR["MON"])
rdef __monochk_ghopt macro
if (!MCK_PAR["IO"]) \
rdef __monochk_beamlost \'\'
else \
rdef __monochk_beamlost \'beamlost = _monochk_beam ()\'
if (!(whatis("user_lineup")&2)) rdef user_lineup \'#\$*\'
}'
#%IU%
#%MDESC% Cleanup service. Disables mono and beam checking features.
def _monochk_cleanup '{
_monochk_log ("CLEANUP")
if (!MCK_ON) { offmonochk }
MCK_SCANNINGMONO=0
MCK_WAITINGFORBEAM=0
}'
#%IU%
#%MDESC% Setup menu.
def _monochk_menu '{
local n i str1 str2 n1 n2
n = "\n"
n1 = "%" n
n2 = "sec." n
for (str1 = "",i=0;i<COUNTERS;i++) { str1 = str1 cnt_mne(i) " " }
str2 = str1 "0"
menuoptval (-44,n,"monitor counter mnemonic",MCK_PAR["MON"])
menuvarlist ("MCK_PAR[\"MON\"]",str1)
menuoptval (-45,n1,"intensity high threshold",MCK_PAR["MTHR"])
menuvargetv ("MCK_PAR[\"MTHR\"]")
menuoptval (-48,n2,"integration time",MCK_PAR["TIME"])
menuvargetv ("MCK_PAR[\"TIME\"]")
menuoptval (-44,n,"machine current counter mnemonic",MCK_PAR["IO"])
menuvarlist ("MCK_PAR[\"IO\"]",str2)
menuoptval (-45,n1,"current low threshold",MCK_PAR["IOTHR"])
menuvargetv ("MCK_PAR[\"IOTHR\"]")
menuoptval (-48,n2,"sleep time after beam is back",MCK_PAR["SLEEP"])
menuvargetv ("MCK_PAR[\"SLEEP\"]")
for (str1 = "",i=0;i<MOTORS;i++) { str1 = str1 motor_mne(i) " " }
print
print "( lineup",MCK_PAR["MOT"],-MCK_PAR["MAG"],MCK_PAR["MAG"], MCK_PAR["STEPS"],MCK_PAR["TIME2"],")"
print
menuoptval (-30,n,"mono motor mnemonic",MCK_PAR["MOT"])
menuvarlist ("MCK_PAR[\"MOT\"]",str1)
menuoptval (-30,n,"line up at",MCK_PAR["MAX"])
menuvarlist ("MCK_PAR[\"MAX\"]","COM CEN PK")
menuoptval (-30,n,"scan magnitude",MCK_PAR["MAG"])
menuvargetv ("MCK_PAR[\"MAG\"]")
menuoptval (-30,n,"scan intervals",MCK_PAR["STEPS"])
menuvargetv ("MCK_PAR[\"STEPS\"]")
menuoptval (-30,n,"scan integration time",MCK_PAR["TIME2"])
menuvargetv ("MCK_PAR[\"TIME2\"]")
menuoptval (-30,n,"plot filter",MCK_PAR["PLOT"])
menuvarlist ("MCK_PAR[\"PLOT\"]","1 2 3 4 5")
menuoptval (-30,n,"scan magnitude after beam loss",MCK_PAR["MAG2"])
menuvargetv ("MCK_PAR[\"MAG2\"]")
menuoptval (-30,n,"scan intervals after beam loss",MCK_PAR["STEPS2"])
menuvargetv ("MCK_PAR[\"STEPS2\"]")
}'
#%UU%
#%MDESC% Disables the mono and beam checking features.
def offmonochk '
MCK_ON = MCK_SCANNINGMONO = 0
rdef chk_beam "break"
print "Mono check is OFF."
_monochk_log("MONO CHK TURNED OFF")
'
#%UU% [counting_interval]
#%MDESC% Enables the mono and beam checking features.%BR%
# Note that the "beam check" is only activated if a machine current monitor has been specified in %B%monochksetup%B%.
# The macro measures the monitor rate and estimates the type of monitor device (analog or integrating). It uses by default the integration time given at setup.%BR%
def onmonochk '{
local t m
t = ($1)
m = ($2)
if (!MCK_SETUP_OK) {
print "Mono check cannot be activated. "
tty_cntl("so")
printf ("monochksetup ")
tty_cntl("se")
print "has not been done or has been done wrong."
exit
}
if (m <= 0){
count_em (t?t:COUNT)/2
waitcount
get_counts
MCK_RATE = (MON >= 0 && S[sec]!=0)? S[MON]/S[sec] : 0
if (cnt_num(MCK_PAR["IO"])!=-1)
MCK_BRATE = (S[sec]!=0)? S[cnt_num(MCK_PAR["IO"])]/S[sec] : 0
count_em (t?t:COUNT)
waitcount
get_counts
MCK_ANALOG = (MON >= 0 && S[MON] != 0 && S[sec] != 0 && \
MCK_RATE/(S[MON]/S[sec]) > 1.5)
if (cnt_num(MCK_PAR["IO"])!=-1)
MCK_BANALOG = (S[cnt_num(MCK_PAR["IO"])] != 0 && S[sec] != 0 && \
MCK_BRATE/(S[cnt_num(MCK_PAR["IO"])]/S[sec]) > 1.5)
} else {
S[sec] = t
if (MON >= 0)
S[MON] = m
MCK_ANALOG = ("$3" == "analog")
}
_onmonochk
}'
#%IU%
#%MDESC% Activates the mono and beam checking features. This macro is called
# from within %B%onmonochk%B%.
def _onmonochk '
if (MON<0 || !MCK_ANALOG&&S[sec]==0 || MON == sec || \
(MCK_RATE=MCK_ANALOG?S[MON]:S[MON]/S[sec])<=0 ) {
rdef chk_beam "break"
print "ERROR: Mono check not activated. "
print "The beam is down or the timer and the monitor are not properly set up."
_monochk_log(sprintf("ERROR ACTIVATING MONO CHK %d %d %g %g",MON,sec,S[sec],MCK_RATE))
exit
}
printf("Mono check is ON. ")
MCK_THRESHOLD = MCK_PAR["MTHR"] / 100 * MCK_RATE
if (MCK_PAR["IO"]) {
MCK_BEAMTHRESHOLD = MCK_PAR["IOTHR"] / 100 * MCK_BRATE
printf("\nMachine current \`%s\` (%s), threshold value: %g\n", \
cnt_name(cnt_num(MCK_PAR["IO"])), MCK_PAR["IO"], MCK_BEAMTHRESHOLD)
}
if (MCK_ANALOG) {
printf("Analog monitor \`%s\' (%s), threshold value: %g\n", \
cnt_name(MON), cnt_mne(MON), MCK_THRESHOLD)
} else {
printf("Integrating monitor \`%s\' (%s), threshold rate: %g/s\n", \
cnt_name(MON), cnt_mne(MON), MCK_THRESHOLD)
}
MCK_ON = 1
rdef chk_beam "if (_monochk ()) break;;"
_monochk_log(sprintf("ACTIVATING MONO CHK; thresholds: %g %g",MCK_THRESHOLD,MCK_BEAMTHRESHOLD))
'
#%IU% ()
#%MDESC% HERE IS THE CORE OF THE MONO CHECK ACTIVITY, hooked to %B%chk_beam%B% standard macro. It decides what to do in case of intensity loss. It is called after each counting of a scan. If the mono rate goes below its threshold, the macro first check the machine current. If the beam appears to be lost, (current monitor below its threshold), the macro waits till it is back, and then wait for a stabilisation period, before doing a pre scan and then the line-up scan on the mono. Then the foreground scan resumes. If the mono intensity is too low, but the machine current is high enough, the macro lines the mono up on its maximum of intensity before continuing the foreground scan. The thresholds are re-adjusted each time the mono is moved (done by %B%_monochk_threshold%B%).
#%BR%
#It is possible to adapt that "mono check" feature to particular needs, by defining 3 user macros :
#%DL%
#%DT%user_scan_mono%DD% called before each ghost line up scan of the mono when the %B%_monochk()%B% has detected it needs to be re-aligned. ("return 0" to skip the line-up and return to %B%chk_beam%B% directly.)
#%DT%user_lineup%DD% called after each re-alignement of the mono.
#%DT%user_beam_is_back%DD% called after beam recovery and before pre-scanning the mono. ("return 1" to skip the pre-scan and return to %B%chk_beam%B% directly.)
#%XDL%
#
#
def _monochk () '{
if (!MCK_ON || set_sim(-1))
return (1)
if (!S[sec] || MON < 0) {
MCK_RATE = MCK_BRATE = 0
} else {
MCK_RATE = MCK_ANALOG? S[MON] : S[MON]/S[sec]
if (-1!=cnt_num(MCK_PAR["IO"]))
MCK_BRATE = MCK_BANALOG? S[cnt_num(MCK_PAR["IO"])] : S[cnt_num(MCK_PAR["IO"])]/S[sec]
}
if (!MCK_WAITINGFORBEAM) {
tty_cntl("md")
p "_monochk: MCK_RATE = " MCK_RATE ". MCK_THRESHOLD = " MCK_THRESHOLD
if (MCK_PAR["IO"]) {
p "_beamchk: current = " MCK_BRATE ". MCK_BEAMTHRESHOLD = " MCK_BEAMTHRESHOLD
}
tty_cntl("me")
}
_monochk_log(sprintf("MONO CHECKING TIME %g %g %g %g",MCK_RATE,MCK_THRESHOLD,MCK_BRATE,MCK_BEAMTHRESHOLD))
if (MCK_RATE >= MCK_THRESHOLD) {
if (MCK_WAITINGFORBEAM) {
local duration unit
duration = time()-MCK_WAITDELAY
if (duration>3600) {
duration/=3600
unit = "hour(s)"
} else if (duration>60) {
duration/=60
unit = "minute(s)"
} else unit = "seconds"
printf("Beam back. (been waiting %.2g %s ...) \n",duration,unit)
printf("Waiting for temperature stabilization...%g sec. \n", MCK_PAR["SLEEP"])
_monochk_log(sprintf("BEAM IS BACK after %g %s",duration,unit))
sleep (MCK_PAR["SLEEP"])
}
# user_end_monochk
MCK_WAITINGFORBEAM=0
MCK_SCANNINGMONO = 0
return 1
} else {
if (!_monochk_beamlost ()) {
if (MCK_SCANNINGMONO) {
MCK_MONO_ITER++
} else {
MCK_MONO_ITER=0
}
printf("Mono Needs Tuning (%s)\n", date())
user_scan_mono MCK_PAR["MOT"]
_monochk_log(sprintf("RESCAN MONO %d",MCK_MONO_ITER))
if (MCK_MONO_ITER > 4) {
printf("PANIC, still below criteria. Two many tuning iterations\n")
printf("Monitor rate : %g, Criteria : %g\n",MCK_RATE,MCK_THRESHOLD)
if (-1!=cnt_num(MCK_PAR["IO"])) {
printf("Beam monitor : %g",S[cnt_num(MCK_PAR["IO"])])
printf(", Beam threshold : %g\n",MCK_BEAMTHRESHOLD)
}
else print "Beam might be down..."
# exit
print "Next trial in 5 minutes..."
sleep(300)
}
printf(" Scanning for maximum of intensity ...")
__scan_mono
MCK_SCANNINGMONO=1
if (MCK_LOG) {
_monochk_logon
print "SCAN ARRAY ",GHDATA
if (GHRES["peak_found"]) {
print "peak found"
print MCK_PAR["MAX"],GHRES["peak_pos"]
} else {
print "no peak found"
print "mono back to",GHRES["prev_pos"]
}
_monochk_logoff
}
}
}
return 0
}'
#%IU%
#%MDESC% If the mono was moved and its monitor rate just measured is high enough (at least 80 percent of old threshold), that macro re-adjusts the thresholds. It is hooked to %B%user_getcounts%B%.
def _monochk_threshold '{
if (MCK_SCANNINGMONO) {
if (MON>=0 && S[sec]!=0) \
MCK_RATE=MCK_ANALOG?S[MON]:S[MON]/S[sec]
else MCK_RATE = 0
if (cnt_num(MCK_PAR["IO"])>=0 && S[sec]!=0) \
MCK_BRATE = S[cnt_num(MCK_PAR["IO"])]/S[sec]
else MCK_BRATE = 0
if (MCK_RATE > MCK_THRESHOLD*0.8) {
MCK_THRESHOLD = MCK_PAR["MTHR"] / 100 * MCK_RATE
if (MCK_PAR["IO"]) {
MCK_BEAMTHRESHOLD = MCK_PAR["IOTHR"] / 100 * MCK_BRATE
}
_monochk_log(sprintf("THRESHOLDS: %g %g",MCK_THRESHOLD,MCK_BEAMTHRESHOLD))
}
}
}'
#%IU% ()
#%MDESC% Checks machine current.
def _monochk_beamlost () '{
local beamlost
beamlost = 0
__monochk_beamlost
return beamlost
}'
#%IU% ()
#%MDESC% Checks machine current. Called from %B%_monochk_beamlost ()%B%.
def _monochk_beam () '{
if (MCK_BRATE < MCK_BEAMTHRESHOLD) {
if (!MCK_WAITINGFORBEAM) {
printf("Beam down on %s\n", date())
printf("Waiting for beam ...\n")
MCK_WAITDELAY = time()
_monochk_log("BEAM DOWN")
}
MCK_WAITINGFORBEAM=1
return 1
}
if (MCK_WAITINGFORBEAM) {
local duration unit
duration = time()-MCK_WAITDELAY
if (duration>3600) {
duration/=3600
unit = "hour(s)"
} else if (duration>60) {
duration/=60
unit = "minute(s)"
} else unit = "seconds"
printf("Beam back: ")
printf("been waiting %.2g %s ... \n",duration,unit)
printf("Waiting for temperature stabilization...%g sec. \n", MCK_PAR["SLEEP"])
_monochk_log(sprintf("BEAM IS BACK after %g %s",duration,unit))
user_beam_is_back
sleep (MCK_PAR["SLEEP"])
MCK_WAITINGFORBEAM=0
printf("Doing a prescan on the mono...")
_monochk_log("PRE SCAN MONO")
__prescan_mono
if (MCK_LOG) {
_monochk_logon
print "PRE SCAN ARRAY ",GHDATA
if (GHRES["peak_found"]) {
print "peak found"
print MCK_PAR["MAX"],GHRES["peak_pos"]
} else {
print "no peak found"
print "mono back to",GHRES["prev_pos"]
}
_monochk_logoff
}
}
return 0
}'
#%IU% (msg)
#%MDESC% Writes message to logfile. Do "MCK_LOG=0" to switch off the logging. File name is e.g. "/tmp/fourc_monochk_Apr1998".
def _monochk_log (msg) '{
global MCK_LOGFILE
local bli n
n=split (date(),bli)
MCK_LOGFILE = sprintf ("/tmp/%s_monochk_%s%s",SPEC,bli[1],bli[n-1])
if (MCK_LOG) {
_monochk_logon;
print " " msg;
_monochk_logoff
}
}'
#%IU%
#%MDESC% Sets logfile on.
def _monochk_logon ' on(MCK_LOGFILE);offt; p "--",SPEC,date()'
#%IU%
#%MDESC% Closes logfile.
def _monochk_logoff 'ont;close(MCK_LOGFILE);'
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# that macro uses %B%ghscans.mac%B%, %B%menu.mac%B% and %B%pseudo.mac%B%.
#%AUTHOR%
# monochk.mac - M.-Claire LAGIER. - 30 th June 1997.
## - May 4 16:41:15 METDST 1998 REV 1.19;
#%TOC%
|