#%TITLE% MAD.MAC
#%NAME%
# Absorption Edge Scanning commands and utilities used for MAD dadacollection
#%CATEGORY% MX
#
#%LOG%
#$Log: MAD.mac,v $
#Revision 1.28 2014/10/03 10:38:10 witsch
#eliminate occurences of plotlist().
#
#Revision 1.27 2012/05/11 13:34:37 beteva
#changed shstate to shstatus to cope with the new beamshutter software
#
#Revision 1.26 2012/03/19 15:38:18 beteva
#changed max to lmax
#
#Revision 1.25 2011/04/29 15:00:55 beteva
#added test if local_mv_undulator exists. Changed != to fabs() > 0.01
#
#Revision 1.24 2011/04/06 08:35:54 guijarro
#changed return(-1) to exit to trigger cleanup in case the macro is aborted
#
#Revision 1.23 2010/11/16 10:04:09 guijarro
#added _ae_shutters_close if attenuation is not found
#
#Revision 1.22 2010/09/09 08:59:40 beteva
#return beamsize in eV instead of keV to make ISPyB happy
#
#Revision 1.21 2010/02/18 17:18:38 beteva
#set AE_STEP as global (only a bug fix)
#
#Revision 1.20 2010/02/12 10:36:14 blissadm
#fixed typo (pritntf -> printf)
#
#Revision 1.19 2010/02/09 13:40:03 beteva
#do tests for division by zero.
#
#Revision 1.18 2009/12/16 11:54:46 beteva
#changed the attenuation scan to be done form +50 to +30 eV over the edge. Added beamX and beamY
#
#Revision 1.17 2009/11/02 16:46:00 beteva
#changed the reading of the transmission, sizeX and sizeY to be before the cleanup (read by ISPyB).
#
#Revision 1.16 2009/04/08 12:05:32 beteva
#added msopen in the attenuation scan
#
#Revision 1.15 2009/02/19 13:41:51 beteva
#change - move undulators after moving the energy (in case undulator scan to be performed)
#
#Revision 1.14 2008/11/25 16:33:54 beteva
#changed the procedures to use transmission factor instead of attenuators set
#
#Revision 1.13 2008/07/31 06:50:14 rey
#documentation changes
#
#Revision 1.12 2008/07/09 15:15:55 guijarro
#do a check_beam() before energy change
#
#Revision 1.11 2008/07/08 13:34:01 guijarro
#return right parameters at the end of energy scan
#
#Revision 1.10 2008/04/09 11:56:29 spruce
#remove wcadjall from attscan. If this is necessary it should be done elsewhere
#
#Revision 1.9 2008/03/20 12:40:17 guijarro
#removed chooch stuff
#
#Revision 1.8 2008/03/19 14:18:52 guijarro
#changed weird "_ae_moveE" function
#
#Revision 1.7 2008/03/06 16:03:53 spruce
#added backin to prepscan
#
#Revision 1.6 2007/02/12 15:04:08 beteva
#changed moveE & getE to mv energy & get_angles; LAMBDA = A[lambda]
#
#Revision 1.5 2006/06/15 08:21:24 beteva
#ae_local_write_choochfile instead of _ae_write_choochfile;
#COLLECT_SEQ["energy"] set because eprodc_set_mono takes no parameters any more;
#no parameter for ae_local_setatt - transmissions factor used;
#
#Revision 1.4 2006/06/06 15:20:28 beteva
#COLLECT_PARS references swapped for mxutils function calls;
#*_ms_shutter changed to ms*; mattset changet to transmission;
#
#Revision 1.3 2006/02/14 13:55:02 beteva
#added wcadjall for the electrometer gains and ATT_FACTOR calculation for mcCuBE
#
#Revision 1.2 2005/11/17 15:23:05 beteva
#changed Xval to eprodc_energy_status;
#added AE_ESCAN_OFFSET for offset durung the energy scan;
#added test_mad and ESCAN_TST* variables to simulate parts of the procedure
#
#Revision 1.1 2005/10/21 09:35:50 beteva
#Initial revision
#
#%END%
#%UU% ()
#%MDESC% First initialisation.
def ae_init() '{
global AE_ELEMENT #element name
global AE_EDGE #edge - K,L
global AE_FILE #Absorption edge datafile
global AE_TUNE #use the parameters fine tunning
global AE_FEUSE #use the front end move in the energy scan
global AE_MCAUSE #use the mca ROI calculations
global AE_MCAROIC #adjust the roi whith this coef [eV]
global AE_MCAROI #roi counter mnemonic
global AE_SCPLOT #scanplot counter mnemonic
global AE_ATTUSE #use the attenuators setup procedure
global AE_E #edge energy [KeV]
global AE_DEAD #[0] time to count [s] ; [1] min level;
#[2] max level; [3] - flag to use deadtime or counts
global AE_SCAN_TIME #scan time [s]
global AE_STEP #step [ev] for the energy scan
global AE_UMOT #Undulator motor(s)
global AE_UMAX #Undulator motor(s) max gap value
global AE_ESCAN_OFFSET #offset for the energyscan from the table values [eV]
global AE_DEBUG #nodebug = 0
global AE_SIMUL #simulate the hardware if != 0
global AE_UND_READY #undulator(s) ready to move OK=0, error=-1
global AE_MONO_READY #mono ready for the escan OK=0, error=-1
global AE_ATTSCAN #attenuation scan status OK=0, error=-1
global AE_TRANSM #keep the transmission factor
global AE_ORG # data out of the datafile
constant AE_Elements 18 #Number of elements in AE_ORG
constant AE_KEN 0
constant AE_KALPHA1 1
constant AE_KALPHA2 2
constant AE_LEN1 3
constant AE_LEN2 4
constant AE_LEN3 5
constant AE_LALPHA1 6
constant AE_LALPHA2 7
constant AE_DISCLO 8
constant AE_DISCHI 9
constant AE_SCANLO1 10
constant AE_SCANLO2 11
constant AE_SCANHI1 12
constant AE_SCANHI2 13
constant AE_NOLAM 14
constant AE_REMOTEK 15
constant AE_REMOTEL 16
constant AE_ELNB 17
global AE_RCM # Recommended values
constant AE_RCM_Elements 9 #Number of elements in AE_RCM
constant AE_RCM_ENERGY 0
constant AE_RCM_DISCLO 1
constant AE_RCM_DISCHI 2
constant AE_RCM_SCANLO1 3
constant AE_RCM_SCANLO2 4
constant AE_RCM_SCANHI1 5
constant AE_RCM_SCANHI2 6
constant AE_RCM_UND 7
global AE_ROOT_DIR
global AE_CHOOCH AE_CHOOCH_FILE
AE_SIMUL = 0
AE_MCAUSE = -1
AE_FEUSE = 0
AE_ATTUSE = 0
}'
#%UU% [file tune mcaroi attenuators undulator(s)]
#%MDESC% setup the input parameters.
def ae_setup '{
local mne i inp nb
ae_init()
if ($# < 2) {
AE_FILE = getval("Absorption edge datafile", AE_FILE)
AE_TUNE = yesno("Further setup", AE_TUNE)
if (AE_TUNE == 1) {
AE_MCAUSE = getval("Which MCA to use (none=-1)", AE_MCAUSE)
if (AE_MCAUSE >= 0) {
AE_MCAROI[0] = getval("ROI counter mnemonic: ", AE_MCAROI[0])
if (cnt_num(AE_MCAROI[0]) == -1) {
eprintf ("invalid counter mnemonic, exiting...\n")
exit
}
}
AE_ATTUSE = yesno("Set the attenuators", AE_ATTUSE)
if (AE_ATTUSE == 1) {
ae_att_param
}
AE_FEUSE = getval("How many undulators to control (none=0): ", AE_FEUSE)
if (AE_FEUSE != 0) {
for (i=0; i<AE_FEUSE; i++) {
mne = getval("Undulator motor mnemonic: ", motor_mne(AE_UMOT[i]))
AE_UMOT[i] = motor_num(mne)
if (AE_UMOT[i] == -1) {
eprintf ("%s - invalid motor mnemonic, exiting...\n", mne)
exit
}
AE_UMAX[i] = getval("Undulator fully open gap: ", AE_UMAX[i])
}
}
ae_scan_param
}
} else {
nb = split("$*", inp)
AE_FILE = inp[0]
AE_TUNE = inp[1]
if (AE_TUNE == 1) {
if (nb <= 2) {
eprintf ("Not enough parameters. Setup not done!\n")
exit
}
AE_MCAUSE = inp[2]
if (AE_MCAUSE >= 0) {
AE_MCAROI[0] = inp[3]
if (cnt_num(AE_MCAROI[0]) == -1) {
eprintf ("invalid counter mnemonic %s, exiting...\n", AE_MCAROI[0])
exit
}
#_mcapar()
}
AE_ATTUSE = inp[4]
ae_att_param inp[5] inp[6] inp[7]
AE_FEUSE = inp[8]
if (AE_FEUSE != 0) {
for (i=0; i<AE_FEUSE; i++) {
AE_UMOT[i] = motor_num(inp[9+2*i])
if (AE_UMOT[i] == -1) {
eprintf ("%s - invalid motor mnemonic, exiting...\n", inp[9+2*i])
exit
}
AE_UMAX[i] = inp[10+2*i]
}
}
}
}
if (file_info(AE_FILE,"-r") == 0) {
eprintf("Cannot open %s, exiting...\n", AE_FILE)
exit
}
#default counting time 1s
AE_SCAN_TIME = 1
#default scan step 1 eV
AE_STEP[0] = AE_STEP[1] = AE_STEP[2] = 1
#default plot counter - mcaroi
AE_SCPLOT = AE_MCAROI[0]
}'
#%UU% [cnt_time ll_dt hl_dt]
#%MDESC% Setup the attenuator scan counting time [s] and low and high
#dead time [percent].
def ae_att_param '{
if ($# == 3) {
AE_DEAD[0] = $1
AE_DEAD[1] = $2
AE_DEAD[2] = $3
} else {
AE_DEAD[0] = getval ("Dead time counted for [s]: ", AE_DEAD[0])
AE_DEAD[1] = getval("Dead time/counts low level [%]: ", AE_DEAD[1])
AE_DEAD[2] = getval("Dead time/counts high level [%]: ", AE_DEAD[2])
}
if (AE_DEAD[2] > 50)
AE_DEAD[3] = 1
else
AE_DEAD[3] = 0
}'
#%UU% [scan_dir time plot_counter E_step1 E_step2 E_step3]
#%MDESC% Setup the energy scan time/point, plot counter and steps [eV].
def ae_scan_param '{
global AE_STEP[]
tty_cntl("md")
print "Running ae_scan_param"
tty_cntl("me")
if ($# == 4) {
AE_ROOT_DIR = "$1"
AE_SCAN_TIME = $2
AE_SCPLOT = "$3"
AE_STEP[0] = AE_STEP[1] = AE_STEP[2] = $4
} else if ($# > 4) {
AE_ROOT_DIR = "$1"
AE_SCAN_TIME = $2
AE_SCPLOT = "$3"
AE_STEP[0] = $4
AE_STEP[1] = $5
AE_STEP[2] = $6
} else {
AE_ROOT_DIR = getval("Directory to keep the scan files: ", AE_ROOT_DIR)
AE_SCAN_TIME = getval ("Energy scan Time/point [s]: ", AE_SCAN_TIME)
AE_SCPLOT = getval("Energy scan plot counter mnemonic: ", AE_SCPLOT)
AE_STEP[0] = getval ("Pre-edge energy step [eV]: ", AE_STEP[0])
AE_STEP[1] = getval ("Edge energy step [eV]: ", AE_STEP[1])
AE_STEP[2] = getval ("Post-edge energy step [eV]: ", AE_STEP[2])
}
ae_choochparam 1
if (cnt_num(AE_SCPLOT) == -1) {
eprintf ("%s - invalid counter mnemonic, exiting...\n", AE_SCPLOT)
exit
}
}'
#%UU% [use_chooch]
#%MDESC% Choose to use or not chooch (Yes = 1). Set the chooch data file.
def ae_choochparam '{
if ($# < 1)
AE_CHOOCH = getval("Do you want to use chooch (1=YES/0=NO): ", AE_CHOOCH)
else
AE_CHOOCH = $1
if (AE_CHOOCH == 1)
AE_CHOOCH_FILE = sprintf("%s/data.raw",AE_ROOT_DIR)
}'
#%UU% [element edge]
#%MDESC% Recommended values in function of %B%element%B% and
#%B%edge%B% as foillows:%BR%
# %B%EDGE:%B%%BR%
# K or L1, L2 and L3 energy%BR%
# %B%MAD:%B%%BR%
# number of wavelengths and remote energy%BR%
# %B%MCA:%B%%BR%
# low and high level discriminator settings%BR%
# %B%SCAN%B%%B%INTERVALS:%B%%BR%
# Pre-edge, Edge and Post-Edge%BR%
# %B%UNDULATOR%B%%B%SETTINGS:%B%%BR%
# gap and max power.
def ae_getedge '{
local elem edge
if ($# < 2) {
elem = getval("Element: ", AE_ELEMENT)
edge = getval("Edge (K/L): ", AE_EDGE)
} else {
elem = "$1"
edge = "$2"
}
if (AE_DEBUG > 0)
printf ("running _ae_getedge(%s, %s)\n", elem, edge)
if (_ae_getedge(elem, edge) == -1) {
eprintf ("Error getting energy values\n")
exit
}
}'
#%UI% (elem, edge)
#%MDESC% Calculate the roi, gap and scan parameters, using the
#datafile, as function of the %B%elem%B% and %B%edge%B% parameters .
def _ae_getedge(elem, edge) '{
local i line nb ftemp tmp
local ae_remote gap
# clean the tables
for (i=0; i < AE_Elements; i++)
AE_ORG[i] = -1
for (i=0; i < AE_RCM_Elements; i++)
AE_RCM[i] = -1
i=0
# read values, print information and fill an array with recommended values
line = getline(AE_FILE)
while (line != -1) {
nb = split(line, ftemp)
if ((ftemp[1] == elem) && (ftemp[2] == edge)) {
i++
break
}
line=getline(AE_FILE)
}
# close file
getline(AE_FILE, "close")
if (i != 1)
return(-1)
AE_ELEMENT = elem
AE_EDGE = edge
for (i = 0; i<nb-3; i++) {
sscanf(ftemp[i+3],"%f",tmp)
AE_ORG[i]=tmp
}
AE_ORG[AE_ELNB] = ftemp[0]
if (edge == "K") {
AE_RCM[AE_RCM_ENERGY] = AE_ORG[AE_KEN]
AE_E = AE_ORG[AE_KEN]
ae_remote = AE_ORG[AE_REMOTEK]
} else {
AE_RCM[AE_RCM_ENERGY]=AE_ORG[AE_LEN3]
AE_E = AE_ORG[AE_LEN3]
ae_remote = AE_ORG[AE_REMOTEL]
}
if (AE_DEBUG > 0)
ae_printEdgeInfo(elem, edge)
# Set recommended discriminator values
AE_RCM[AE_RCM_DISCLO]=AE_ORG[AE_DISCLO]
AE_RCM[AE_RCM_DISCHI]=AE_ORG[AE_DISCHI]
# Set recommended scan values
AE_RCM[AE_RCM_SCANLO1] = AE_ORG[AE_SCANLO1]
AE_RCM[AE_RCM_SCANLO2] = AE_ORG[AE_SCANLO2] + AE_ESCAN_OFFSET
AE_RCM[AE_RCM_SCANHI1] = AE_ORG[AE_SCANHI1] + AE_ESCAN_OFFSET
AE_RCM[AE_RCM_SCANHI2] = AE_ORG[AE_SCANHI2]
if (AE_FEUSE > 0) {
for (i=0; i<AE_FEUSE; i++) {
gap[0] = _ae_wwave(motor_mne(AE_UMOT[i]),AE_E,0)
if (gap[0]< 0)
AE_RCM[AE_RCM_UND+i] = AE_UMAX[i]
else {
AE_RCM[AE_RCM_UND+i] = gap[0]
if (ae_remote > 0)
gap[1] =_ae_wwave(motor_mne(AE_UMOT[i]),ae_remote,1)
#if (gap[1] < 0)
# AE_RCM[AE_RCM_UND+i] = AE_UMAX[i]
}
}
if ((fabs(AE_RCM[AE_RCM_UND] - AE_UMAX[0]) > 0.01) && \
(fabs(AE_RCM[AE_RCM_UND+1] - AE_UMAX[1]) > 0.01)) {
AE_RCM[AE_RCM_UND] = AE_UMAX[0]
}
}
return(0)
}'
#%UI% _ae_wwave(umne,le,rem)
#%MDESC% Calculate the undulator %B%ume%B% gap as function of the
#energy (le < 3.5) or the wavelength (le > 1000).
def _ae_wwave(umne,le,rem) '{
if (le <= 0) {
return(-1)
}
if (le < 3.5) {
en = hc_over_e*1000/le
} else {
if (le > 1000) {
en=le;
le=hc_over_e*1000/en
} else
return(-1)
}
ae_local_wwave motor_num(umne) le rem
gap = AE_GAP
if (gap != -1) {
# plot values if needed
if (AE_DEBUG == 1) {
if (rem == 1)
rem = "remote energy"
else
rem = "edge energy"
printf("-----------------------------------------------------\n")
printf("\tSUMMARY OF DATA FOR %s %s\n", umne, rem)
printf("-----------------------------------------------------\n")
printf(" Gap value : %6.4f\n", gap)
printf(" Energy : %2.3f KeV (wavelength %2.5f )\n",en/1000,le)
}
}
return(gap)
}'
#%UI%(elem,edge)
#%MDESC% Verbose print of information after the getedge calculations.
def ae_printEdgeInfo(elem,edge) '{
global ae_rem
printf("EDGE INFORMATION - %s:\n", elem);
if (edge == "K") {
printf("\tK edge energy: %2.4f KeV\n", AE_ORG[AE_KEN]/1000)
ae_rem = AE_ORG[AE_REMOTEK]
} else {
printf("\tL3 edge energy: %2.4f\n",AE_ORG[AE_LEN3]/1000)
printf("\tL2 edge energy: %2.4f\n", AE_ORG[AE_LEN2]/1000)
printf("\tL1 edge energy: %2.4f\n", AE_ORG[AE_LEN1]/1000)
ae_rem = AE_ORG[AE_REMOTEL]
}
if (AE_MCAUSE >= 0) {
printf("MCA INFORMATION:\n");
printf("\tLower level: %6.2f\n", AE_ORG[AE_DISCLO])
printf("\tHigher level: %6.2f\n", AE_ORG[AE_DISCHI])
}
printf ("SCAN INFORMATION:\n")
if (AE_STEP[0] != AE_STEP[1])
printf("\tPre-edge : %2.4f to %2.4f KeV, %d eV step\n", AE_ORG[AE_SCANLO1]/1000, AE_ORG[AE_SCANLO2]/1000, AE_STEP[0])
printf("\tEdge : %2.4f to %2.4f KeV, %d eV step\n", AE_ORG[AE_SCANLO2]/1000, AE_ORG[AE_SCANHI1]/1000,AE_STEP[1])
if (AE_STEP[2] != AE_STEP[1])
printf("\tPost-Edge: %2.4f to %2.4f KeV, %d eV step\n", AE_ORG[AE_SCANHI1]/1000, AE_ORG[AE_SCANHI2]/1000, AE_STEP[2])
printf("MAD INFORMATION\n");
printf("\tNumber of wavelengths: %f\n", AE_ORG[AE_NOLAM])
printf("\tRemote energy : %3.4f Kev\n", ae_rem)
}'
#%UI% (t,flag)
#%MDESC% Get the deadtime from the mca for count time %B%t%B%. If no flag,
#retun the dead time [s], else return the count rate for the ROI.
def _deadct(t,flag) '{
local double array adcinfo[8]
if (t <= 0) {
eprintf("Count time not set, exiting...\n")
return(-1)
}
if (flag == 0) {
#msopen
sleep(t)
#msclose
esrf_io(mca_spar(AE_MCAUSE, "device_id"), "DevMcaGetAdcInfo",adcinfo)
#return(MCA_TIMES[AE_MCAUSE]["dead"])
return(adcinfo[6])
} else {
#msopen
tcount(t); waitcount;get_counts
#msclose
return (S[cnt_num(AE_MCAROI[0])]/t)
}
}'
#%UI% (scan_energy)
#%MDESC% Do energy scan +- 0.1 KeV around %B%scan_energy%B%.
def _deadscan(scan_energy) '{
local lmax
printf("SCAN AROUND EDGE ENERGY\n")
msopen
Escan scan_energy-0.1 scan_energy+0.1 20 0.5
msclose
lmax=array_op("max",SCAN_D[][dead+1])
printf("Max energy in scan: %x\n",lmax)
return(lmax)
}'
#%UI% ()
#%MDESC% Open all shutters.
def _ae_shutters_open() '{
if (AE_SIMUL == 0)
shopen
if (AE_DEBUG > 0)
printf("Open the fast shutter\n")
if (AE_SIMUL == 0)
msopen
}'
#%UI% ()
#%MDESC% Close all shutters.
def _ae_shutters_close() '{
if (AE_DEBUG > 0)
printf("Close the fast shutter\n")
if (AE_SIMUL == 0)
msclose
ae_local_shutters_close
if (AE_SIMUL == 0)
shclose
}'
#%UI% ()
#%MDESC% Set the apropriate attenuator set before a scan.
def ae_setattenuator() '{
local i dtc mystr
#read the present attenuation
AE_TRANSM = ATT_FACTOR
# put in max attenuation
transmission 0
dtc = _deadct(AE_DEAD[0],AE_DEAD[3])
if (dtc == -1) {
egui_logmsg("Cannot read the detector dead time/counts, giving up.")
return(-1)
}
mystr = sprintf("%s",(AE_DEAD[3]==0?"deadtime":"counts"))
if (dtc > AE_DEAD[2]) {
egui_logmsg("The detector is saturated, giving up.")
eprintf ("Saturation %s %g\n", mystr, dtc)
return (-1)
}
printf ("%s %g\n", mystr, dtc)
for (i=1; i < NR_MATT; i++) {
# Not enough detection, take out some attenuation
transmission MATT_TABLE[i]
mystr = sprintf ("Transmission factor %g\%\n", ATT_FACTOR)
egui_logmsg(mystr)
dtc = _deadct(AE_DEAD[0],AE_DEAD[3])
printf ("%s %g\n", mystr, dtc)
if (dtc > AE_DEAD[1]) break;
}
if (dtc < AE_DEAD[1]) {
mystr = sprintf("Could not find satisfactory attenuation (is the mca properly set up?), giving up.")
egui_logmsg(mystr)
eprintf("%s\n", mystr)
eval(sprintf ("transmission %f", AE_TRANSM))
return (-1)
}
return (0)
}'
#%UI% (ind)
#%MDESC% Check if the undulator %B%ind%B% can move. Return 0 if OK, -1 if not.
def _ae_checkundulator(ind) '{
global AE_UND_READY
AE_UND_READY = 0
eval (sprintf("ae_local_checkundulator %d",ind))
return(AE_UND_READY)
}'
#%UI% (ind,val)
#%MDESC% Move the undulator %B%ind%B% to the calculated gap %B%val%B%.
def _ae_moveundulator(ind,val) '{
local str
ESRF_ERR = -1
if (_ae_checkundulator(ind) == -1) {
eprintf ("Error with the undulator, will not move\n")
return(-1)
}
printf ("Now will move the undulator %s\n", motor_mne(AE_UMOT[ind]))
if ((fabs(A[AE_UMOT[ind]] - AE_RCM[val]) > 0.01) && (AE_RCM[val] != 0)) {
str = sprintf("%s %f",motor_mne(AE_UMOT[ind]),AE_RCM[val])
if (AE_DEBUG > 0)
egui_logmsg(sprintf("Moving undulator: mv %s\n", str))
if (AE_SIMUL == 0) {
get_angles
if ((A[AE_UMOT[ind]] < AE_UMAX[ind]) || \
(fabs(AE_RCM[val] - AE_UMAX[ind]) > 0.01)) {
A[AE_UMOT[ind]] = AE_RCM[val]
move_em; move_poll
if (ESRF_ERR != 0) {
eprintf ("Cannot move undulator %s\n", str)
return (-1)
}
} else {
if (ismacro("local_mv_undulator")) {
eval(sprintf ("local_mv_undulator %d %f", ind, AE_RCM[val]))
}
}
}
} else {
printf ("Undulator will not move\n")
}
return(0)
}'
#%UI% ()
#%MDESC% Move the undulator(s) to the calculated gaps.
def _ae_moveundulators() '{
local flag stat
flag = 0
get_angles
if (AE_FEUSE == 1) {
#move one (the first) undulator
_ae_moveundulator(0,AE_RCM_UND)
} else if (AE_FEUSE == 2) {
#move two undulators
if (AE_RCM[AE_RCM_UND] == AE_UMAX[0]) {
if (_ae_moveundulator(0,AE_RCM_UND) < 0)
return(-1)
flag = 1
} else if (AE_RCM[AE_RCM_UND+1] == AE_UMAX[1]) {
if (_ae_moveundulator(1,AE_RCM_UND+1) < 0)
return(-1)
flag = 2
}
if (AE_DEBUG > 0)
printf ("should move undulator %d\n",flag)
if (flag == 1) {
if (_ae_moveundulator(1,AE_RCM_UND+1) < 0)
return(-1)
} else if (flag == 2) {
if (_ae_moveundulator(0,AE_RCM_UND) < 0)
return(-1)
}
}
return (0)
}'
#%UI% ()
#%MDESC% Prepare the mono for the escan. Return 0 if OK, -1 if error.
#(set in the AE_MONO_READY variable).
def ae_prepare_mono() '{
global AE_MONO_READY
AE_MONO_READY = 0
ae_local_prepare_mono
return (AE_MONO_READY)
}'
#%UI% ()
#%MDESC% Restore the mono after the escan. Return 0 if OK, -1 if error
#(set in the AE_MONO_READY variable).
def ae_restore_mono() '{
global AE_MONO_READY
AE_MONO_READY = 0
ae_local_restore_mono
return (AE_MONO_READY)
}'
#%UI% (offset)
#%MDESC% Move the mono to the edge+%B%offset%B% energy.
def _ae_moveE(offset) '{
local msg
msg = sprintf ("Moving to %g+%d eV", AE_E, offset)
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
en = ((AE_E + offset)/1000)
get_angles
A[energy]=en
move_em
waitmove
#mv energy en
#get_angles
#LAMBDA = A[lambda]
#if ((hc_over_e/LAMBDA <= en-0.002) || (hc_over_e/LAMBDA > en+0.002)) {
# return (-1)
#}
#if ((A[energy] <= en-0.002) || (A[energy] > en+0.002)) {
# return (-1)
#}
return (0)
}'
#%UI% ()
#%MDESC% Prepare the edge scan.
def _ae_prepscan() '{
local en
global OLD_DATAFILE
OLD_DATAFILE = DATAFILE
ae_on
# Move fluorencent detector
if (AE_DEBUG > 0) {
printf("Get the backlight out\n")
printf("Move fluorescence detector\n")
}
if (AE_SIMUL == 0) {
lightout
fldetin
backin
msopen
}
if (AE_ATTUSE == 1) {
en = ((AE_E + 30)/1000)
eprodc_energy_scan_status("Setting the attenuation..")
ae_local_setatt
}
if (AE_MCAUSE >= 0) {
plotselect AE_SCPLOT
if (AE_SIMUL == 0)
ae_local_mcaroi
mcaoff
}
return(0)
}'
#%UU% ()
#%MDESC% Choose appropriate attenuation. Return 0 if OK, -1 if no
#attenuation found (set in AE_ATTSCAN variable).
def ae_attscan() '{
global AE_ATTSCAN
AE_ATTSCAN = 0
ae_local_attscan
return (AE_ATTSCAN)
}'
#%UI% ()
#%MDESC% Choose appropriate attenuation. Return 0 if OK, -1 if no
#attenuation found (set in AE_ATTSCAN variable).
def _ae_attscan() '{
local en
# Move fluorencent detector
if (AE_DEBUG > 0)
printf("Move fluorescence detector\n")
if (AE_SIMUL == 0)
fldetin
if (AE_MCAUSE >= 0) {
if (MCA_GUI == 0)
mcaguion
mcaon
ae_local_mcaroi
}
#open again the shutter (security feature)
if (AE_SIMUL == 0)
msopen
if (AE_ATTUSE == 1) {
en = ((AE_E + 30)/1000)
eprodc_energy_scan_status("Setting the attenuation..")
if (AE_MCAUSE >= 0)
mcaclear
ae_local_setatt
}
if (AE_SIMUL == 0) {
if (AE_ATTUSE == 1) {
if (ae_setattenuator() == -1) {
AE_ATTSCAN = -1
return(-1)
}
}
}
AE_ATTSCAN = 0
return(0)
}'
#%UI%()
#%MDESC% Select which counter to plot during the scan.
def ae_plotselect() '{
if (AE_MCAUSE >= 0) {
plotselect AE_SCPLOT
} else {
ae_local_plotselect
}
}'
#%UI%()
#%MDESC% Do Escan or XEscan.
def ae_scan() '{
float array params[32]
if (AE_STEP[0] == 0) {
eprintf ("Scan step unefined, giving up\n")
eprodc_energy_scan_status("Scan step unefined, giving up")
return (-1)
}
if (AE_STEP[1] == 0) {
eprintf ("Scan step unefined, giving up\n")
eprodc_energy_scan_status("Scan step unefined, giving up")
return (-1)
}
if (AE_STEP[2] == 0) {
eprintf ("Scan step unefined, giving up\n")
eprodc_energy_scan_status("Scan step unefined, giving up")
return (-1)
}
params[0] = AE_RCM[AE_RCM_SCANLO1]/1000
params[1] = AE_RCM[AE_RCM_SCANLO2]/1000
params[2] = (AE_RCM[AE_RCM_SCANLO2] - AE_RCM[AE_RCM_SCANLO1]) / AE_STEP[0]
params[3] = AE_RCM[AE_RCM_SCANHI1]/1000
params[4] = (AE_RCM[AE_RCM_SCANHI1] - AE_RCM[AE_RCM_SCANLO2]) / AE_STEP[1]
params[5] = AE_RCM[AE_RCM_SCANHI2]/1000
params[6] = (AE_RCM[AE_RCM_SCANHI2] - AE_RCM[AE_RCM_SCANHI1]) / AE_STEP[2]
params[7] = AE_SCAN_TIME
if (AE_SIMUL == 0) {
DATAFILE = AE_DATAFILE
eprodc_energy_scan_status("Doing the scan..")
msopen
if ((AE_STEP[0] == AE_STEP[1]) && (AE_STEP[0] == AE_STEP[2])) {
printf(" Edge.....: %6.3f to %6.3f KeV, %4.2f eV step\n", params[1] , params[3], params[4])
ae_local_Escan params[1] params[3] params[4] params[7]
} else {
printf(" Pre-edge.: %6.3f to %6.3f KeV, %4.2f eV step\n", params[0] , params[1], params[2])
printf(" Edge.....: %6.3f to %6.3f KeV, %4.2f eV step\n", params[1] , params[3], params[4])
printf(" Post-edge: %6.3f to %6.3f KeV, %4.2feV step\n", params[3] , params[5], params[6])
XEscanf(params,8)
}
DATAFILE = OLD_DATAFILE
if (AE_CHOOCH ==1)
ae_local_write_choochfile(AE_CHOOCH_FILE)
}
}'
#%UI% ()
#%MDESC% To do after the scan.
def _ae_postscan() '{
if (AE_SIMUL == 0) {
fldetout
if (AE_MCAUSE >=0) {
mcaoff
mcaguioff
}
eval(sprintf ("transmission %f", AE_TRANSM))
}
close(DATAFILE)
close(AE_DATAFILE)
DATAFILE = OLD_DATAFILE
return(0)
}'
#%UU%
#%MDESC% To be be called in case of errors in the energy scan.
def ae_cleanup '{
global AE_DOSCAN
AE_DOSCAN = 0
eprodc_energy_scan_status("Scan aborted, cleaning up...")
_ae_shutters_close()
_ae_postscan()
}'
#%IU%
#%MDESC% Keep the initial motor positions.
def _poskeep() '{
local i
global AE_A[]
get_angles; waitmove
for (i=0; i<MOTORS;i++)
AE_A[i] = A[i]
}'
#%IU%
#%MDESC% Restore the initial motor positions.
def _posrestore() '{
local i
for (i=0; i<MOTORS;i++)
A[i] = AE_A[i]
move_em; waitmove
}'
#%IU% (fname)
#%MDESC% Write a file to be used by autochooch.
def _ae_write_choochfile(fname) '{
local ae_cnt i maxcounts scalefactor curr_x_point
printf ("Removing choochfile %s\n", fname)
unix(sprintf("/bin/rm -f %s",fname))
printf ("Creating new choochfile %s\n", fname)
open(fname)
fprintf(fname,"%s on %s\n", HEADING, DATE)
fprintf(fname,"%d\n",NPTS-1)
ae_cnt = cnt_num(AE_SCPLOT)+1
maxcounts = 0
scalefactor = 1
maxcounts = array_op("max",SCAN_D[ae_cnt])
if (maxcounts == 0) {
close(fname)
return(-1)
}
if (maxcounts < 10)
scalefactor = 10/maxcounts
for (i=0; i<NPTS; i++) {
#just in case the mono motor values are the same, which screws up benny???
if (curr_x_point - SCAN_D[i][0]*1000 == 0) {
curr_x_point = SCAN_D[i][0]*1000 + 1
printf ("Modified energy value for chooch input file\n", curr_x_point)
} else {
curr_x_point = SCAN_D[i][0]*1000
}
fprintf (fname,"%6.2f %f\n", curr_x_point,\
fabs(SCAN_D[i][ae_cnt]*scalefactor))
curr_x_point = SCAN_D[i][0]*1000
}
close(fname)
}'
#%IU% [filename]
#%MDESC% Get a filename for the energy scans.
def ae_newfile '{
global AE_DATAFILE
local fname fn[] ae_file
if ($# == 0)
fname = getval("Energy scans filename (name only): ",fname)
else
fname = "$1"
split(date(),fn)
fname = sprintf ("%s_%s_%s_%s.scan", fname, fn[2], fn[1], fn[4])
ae_file = sprintf("%s/%s", AE_ROOT_DIR, fname)
if (file_info(ae_file) == 1) {
beep
tty_cntl("md")
printf("%s already exist !\n", ae_file)
tty_cntl("me")
} else {
close (AE_DATAFILE)
open(ae_file)
}
AE_DATAFILE = ae_file
tty_cntl("md")
printf("\nSPEC will save the energy scan data in %s !\n",AE_DATAFILE)
tty_cntl("me")
}'
#%UU% (edge,prefix)
#%MDESC% Do an energy scan. The %B%edge%B% is a string comprising the
#chemical element and which edege (K or L). Save the scan date in a file
#with %B%prefix%BR name.
def eprodc_do_energy_scan(edge,prefix) '{
local inp[] stat msg
local att
local fn[]
local starte ende exptime
global AE_DATAFILE
global AE_DOSCAN
check_beam()
AE_DOSCAN = 1
ae_on
eprodc_energy_scan_status("")
eprodc_energy_scan_status("Checkup procedure")
# set up the data file for the energy scan
#(should be in local data file as well)
split(date(),fn)
AE_DATAFILE = sprintf("%s/%s_%s_%s_%s.scan", getMxCollectPars("escan_dir"), \
getMxCollectPars("escan_prefix"), fn[2], fn[1], fn[4])
AE_ROOT_DIR = getMxCollectPars("escan_dir")
ae_choochparam 1
#get the attenuation before the scan
AE_TRANSM = ATT_FACTOR
cdef("cleanup_once","ae_cleanup\n","_energy_scan_")
if (ESCAN_TST_FRONTEND == 0) {
eprodc_energy_scan_status("Check if hutch searched")
# Dont waste time if we have not searched the hutch
stat = shstatus("OPEN")
if ((stat != "OPEN") && (stat != "CLOSED")) {
msg = sprintf("Safety shutter disabled, aborted!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
eprodc_energy_scan_status("Check if front end open")
msg = sprintf ("")
stat = _check_fe(0)
if (stat == -1 && AE_SIMUL == 0)
msg = sprintf ("Front End not open, scan aborted!")
if (msg != "") {
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
}
split(edge,inp)
eprodc_energy_scan_status("Look up Edge")
stat = _ae_getedge(inp[0],inp[1])
if (stat == -1) {
msg = sprintf("Cannot calculate the scan parameters, scan aborted!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
eprodc_energy_scan_status("Preset scan parameters")
stat = _ae_prepscan()
if (stat == -1) {
msg = sprintf ("Cannot preset the scan parameters, scan aborted!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
msg = sprintf("Moving mono to %g+30 eV",AE_E)
eprodc_energy_scan_status(msg)
#move to the remote energy
COLLECT_SEQ["energy"]=(AE_E+30)/1000.0
if (eprodc_set_mono() == -1) {
msg = sprintf("Cannot set the mono to %g eV, scan aborted!", AE_E+30)
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
if (ESCAN_TST_UND == 0) {
eprodc_energy_scan_status("Moving undulators")
stat = _ae_moveundulators()
if (stat == -1) {
msg = sprintf ("Cannot move undulators, scan aborted!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
}
eprodc_energy_scan_status("Setting up the attenuation, please wait")
_ae_shutters_open()
if (ESCAN_TST_ATTSCAN == 0) {
stat = ae_attscan()
if (stat == -1 && AE_SIMUL == 0) {
msg = sprintf("Cannot find appropriate attenuation, scan aborted!")
eprodc_energy_scan_status(msg)
printf ("%s\n",msg)
egui_logmsg(msg)
exit
}
}
msclose
if (ae_prepare_mono() != 0) {
msg = sprintf("Mono not ready, procedure aborted!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
ae_plotselect()
msopen
eprodc_energy_scan_status("Doing the Escan now, please wait")
if (ESCAN_TST_ESCAN == 0) {
stat = ae_scan()
if (stat == -1) {
msg = sprintf ("Cannot do the Escan, procedure aborted!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
exit
}
}
_ae_shutters_close()
if (ae_restore_mono() != 0) {
msg = sprintf("Attention, mono setup not restored!")
eprodc_energy_scan_status(msg)
egui_logmsg(msg)
}
eprodc_energy_scan_status("Scan successfully completed, cleaning up")
starte = AE_RCM[AE_RCM_SCANLO2]/1000
ende = AE_RCM[AE_RCM_SCANHI1]/1000
exptime = AE_SCAN_TIME * ((AE_RCM[AE_RCM_SCANHI1] - \
AE_RCM[AE_RCM_SCANLO2]) / AE_STEP[1])
local af
af = getMxCurrentTransmission()
local bsx
bsx = getMxBeamSizeX()*1000.
local bsy
bsy = getMxBeamSizeY()*1000.
_ae_postscan()
eprodc_energy_scan_status("")
egui_logmsg("Energy scan successfully completed")
AE_DOSCAN = 0
return ["transmissionFactor":af, "startEnergy":starte, "endEnergy":ende, "exposureTime":exptime, "beamSizeVertical":bsy, "beamSizeHorizontal":bsx, "theoreticalEdge":AE_E]
}'
def test_mad '{
global ESCAN_TST_FRONTEND ESCAN_TST_UND ESCAN_TST_REALIGN
global ESCAN_TST_ATTSCAN ESCAN_TST_ESCAN
printf ("For testing only, you may choose to simulate the:\n")
ESCAN_TST_FRONTEND = yesno("\tfront end opening?", ESCAN_TST_FRONTEND)
ESCAN_TST_UND = yesno("\tundulator(s) moving?", ESCAN_TST_UND)
ESCAN_TST_REALIGN = yesno("\tquick realignment?", ESCAN_TST_REALIGN)
ESCAN_TST_ATTSCAN = yesno ("\tattenuation scan?", ESCAN_TST_ATTSCAN)
ESCAN_TST_ESCAN = yesno("\tenergy scan?", ESCAN_TST_ESCAN)
}'
#%IU% (keyword)
#%MDESC% Return 1 if the macro named %B%keyword%B% exist, 0 otherwise.
def ismacro(keyword) '{
return ((whatis(keyword)&2)==2)
}'
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
#%B%fldet.mac%B% - insert/extract the fluorescent detector%BR%
#%B%id.mac%B% - undulators%BR%
#%B%matt.mac%B% - attenuators%BR%
#%B%mxautochooch.mac%B% - chooch functions and calls
#%B%mxcollect.mac%B% - auxilary data collection functions%BR%
#%B%mxutils.mac%B% - Utility macros and functions%BR%
#%B%MAD_id**.mac%B% - local MAD functions%BR%
#%B%multimca.mac%B% - mca%BR%
#%B%wagoct.mac%B% - electrometer gains%BR%
#%B%attfactor.mac%B% - transmission factor%BR%
#%TOC%
#%AUTHOR% A.Beteva/BLISS
#$Revision: 1.28 $$Date: 2014/10/03 10:38:10 $
|