#%TITLE% MXUTILS.MAC
#%NAME%
# Utility macros and function for the MX beamlines
#
#%CATEGORY% MX
#
#%END%
#%UU% ([inp])
#%MDESC% Get the MXCOLLECT_PARS paaremeter(s). With no argument returns the
#list of all the existing %B%COLLECT%B% parameters. The input argument
#%B%inp%B% can be a string or an associative array of strings. In both cases
#the return value is either the value of the inp parameter, or an empty string,
#if the specified parameter in not set beforehand. E.g. inp = "mypar" to get
#the MXCOLLECT_PARS[mypar] value; inp[0]="my", inp[1]="par" to get the
#MXCOLLECT_PARS[my][par] value.
def getMxCollectPars(inp) '{
local mask
mask = 0x01000000
if ((whatis("inp")&mask) != mask) {
if (!inp)
return(MXCOLLECT_PARS)
if (!(inp in MXCOLLECT_PARS))
return("")
else
return(MXCOLLECT_PARS[inp])
} else {
if (!(inp[0] in MXCOLLECT_PARS) && !(inp[1] in MXCOLLECT_PARS[inp[0]]))
return("")
else
return(MXCOLLECT_PARS[inp[0]][inp[1]])
}
return("")
}'
#%UU% (inp,val)
#%MDESC%Set the MXCOLLECT_PARS paaremeter %B%inp%B% to a value %B%val%B%. The
#input parameter is a string or an associative array of strings.
def setMxCollectPars(inp,val) '{
local mask
mask = 0x01000000
if ((whatis("inp")&mask) != mask) {
MXCOLLECT_PARS[inp] = val
} else {
MXCOLLECT_PARS[inp[0]][inp[1]] = val
}
}'
#%UU% ([inp])
#%MDESC% Get the MXBCM_PARS paaremeter(s). With no argument returns the
#list of all the existing %B%BCM%B% parameters. The input argument
#%B%inp%B% can be a string or an associative array of strings. In both cases
#the return value is either the value of the inp parameter, or an empty string,
#if the specified parameter in not set beforehand. E.g. inp = "mypar" to get
#the MXBCM_PARS[mypar] value; inp[0]="my", inp[1]="par" to get the
#MXBCM_PARS[my][par] value.
def getMxBcmPars(inp) '{
local mask
mask = 0x01000000
if ((whatis("inp")&mask) != mask) {
if (!inp)
return(MXBCM_PARS)
if (!(inp in MXBCM_PARS))
return("")
else
return(MXBCM_PARS[inp])
} else {
if (!(inp[0] in MXBCM_PARS) && !(inp[1] in MXBCM_PARS[inp[0]]))
return("")
else
return(MXBCM_PARS[inp[0]][inp[1]])
}
return("")
}'
#%UU% (inp,val)
#%MDESC%Set the MXBCM_PARS paaremeter %B%inp%B% to a value %B%val%B%. The
#input parameter is a string or an associative array of strings.
def setMxBcmPars(inp,val) '{
local mask
mask = 0x01000000
if ((whatis("inp")&mask) != mask) {
MXBCM_PARS[inp] = val
} else {
MXBCM_PARS[inp[0]][inp[1]] = val
}
}'
#%UU% ([inp])
#%MDESC% Get the MXSPEC_PARS paaremeter(s). With no argument returns the
#list of all the existing %B%SPEC%B% parameters. The input argument
#%B%inp%B% can be a string or an associative array of strings. In both cases
#the return value is either the value of the inp parameter, or an empty string,
#if the specified parameter in not set beforehand. E.g. inp = "mypar" to get
#the MXSPEC_PARS[mypar] value; inp[0]="my", inp[1]="par" to get the
#MXSPEC_PARS[my][par] value.
def getMxSpecPars(inp) '{
local mask
mask = 0x01000000
if ((whatis("inp")&mask) != mask) {
if (!inp)
return(MXSPEC_PARS)
if (!(inp in MXSPEC_PARS))
return("")
else
return(MXSPEC_PARS[inp])
} else {
if (!(inp[0] in MXSPEC_PARS) && !(inp[1] in MXSPEC_PARS[inp[0]]))
return("")
else
return(MXSPEC_PARS[inp[0]][inp[1]])
}
return("")
}'
#%UU% (inp,val)
#%MDESC%Set the MXSPEC_PARS paaremeter %B%inp%B% to a value %B%val%B%. The
#input parameter is a string or an associative array of strings.
def setMxSpecPars(inp,val) '{
local mask
mask = 0x01000000
if ((whatis("inp")&mask) != mask) {
MXSPEC_PARS[inp] = val
} else {
MXSPEC_PARS[inp[0]][inp[1]] = val
}
}'
#%UU% ()
#%MDESC% Get the wavelength. Returns the current wavelength (for the MAD
#beamlines), the default wavelength or LAMBDA, in case a pseudo motor is set.
def getMxWavelength() '{
local wavelength
local wavmot motnb energymot
wavmot = getMxSpecPars("wavmot")
if (wavmot == "LAMBDA")
return(LAMBDA)
motnb = motor_num(wavmot)
if (motnb == -1) {
energymot = getMxSpecPars("emot")
motnb = motor_num(energymot)
if (motnb == -1)
return(wavmot)
return(hc_over_e/A[motnb])
} else {
return(A[motnb])
}
}'
def getMxEnergy() '{
return(hc_over_e/getMxWavelength())
}'
#%UU% ()
#%MDESC% Get the current detector distance. Returns the current distance
def getMxCurrentDistance() '{
local distance
local motnb
motnb = motor_num(getMxSpecPars("detdistmot"))
if (motnb == -1)
return(-1)
else {
get_angles
return(A[motnb])
}
}'
#%UU% ()
#%MDESC% Get the current transmission
def getMxCurrentTransmission() '{
global ATT_FACTOR
if (whatis("ATT_FACTOR")>>16&0x0400) {
if (whatis("ATT_FACTOR")>>16&0x0800) {
} else {
MXBCM_PARS["curr_transmission"]=ATT_FACTOR
}
}
return(MXBCM_PARS["curr_transmission"])
}'
#%UU% ()
#%MDESC% Get the maximum exposure for a given transmission
def getMxMaximumExposure() '{
MXBCM_PARS["maximum_exposure"]= MXSPEC_PARS["maximum_counts"] * \
MXSPEC_PARS["intensity_calibration_constant"] * \
getMxCurrentTransmission()
}'
#%UU% ()
#%MDESC% Get the detector binning mode (if applicable).
def getMxDetectorBinMode() '{
if (whatis("COLLECT_SEQ[\"detector_mode\"]")>>16&0x8000) {
print "Binning set by data collection parameters"
} else {
print "No binning set by data collection, use default"
COLLECT_SEQ["detector_mode"] = MXSPEC_PARS["detector"]["binning"]
}
return(COLLECT_SEQ["detector_mode"])
}'
#%UU% ()
#%MDESC% Get the detector binning mode (if applicable).
def getMxDetectorFileSuffix() '{
return MXBCM_PARS["FileSuffix"]
}'
#%IU% (diameter)
#%MDESC% Get the detector resolution.
def getMxResolution(diameter) '{
wavelength = getMxWavelength()
distance = dist == 0 ? A[motor_num(getMxSpecPars("detdistmot"))] : dist
distance = distance/1000
corner_angle = atan(diameter/(2*distance))
tsincorner = 2*sin(0.5*corner_angle)
resAtCorner = wavelength/ tsincorner
return(resAtCorner)
}'
#%IU% ()
#%MDESC% Get the detectoer resolution in the corners.
def getMxResolutionAtCorner() '{
diameter = getMxDiameter()/1000
distToCorner = 2*(diameter/pow(2,0.5))
return(getMxResolution(distToCorner))
}'
#%IU% ()
#%MDESC% Get the detectoer resolution at half radius.
def getMxResolutionAtHalfCorner() '{
diameter = getMxDiameter()/1000
distToHalfCorner = (diameter/2+diameter/pow(2,0.5))
return(getMxResolution(distToHalfCorner))
}'
def getMxBeamShape(flag) '{
local shape
if (MXBCM_PARS["original_beam_shape"]=="circular") {
bsx = getMxBeamSizeX(flag)
bsy = getMxBeamSizeY(flag)
if (bsx!=bsy) {
MXBCM_PARS["beam_shape"]="elliptical"
} else {
MXBCM_PARS["beam_shape"]="circular"
}
}
shape = MXBCM_PARS["beam_shape"]
if (shape == 0) { shape = "" }
return shape
}'
#%IU% ()
#%MDESC% Get the detector radius.
def _getRadius() '{
global MXBCM_PARS
float array tmp[4]
diameter = 2*getMxBcmPars("detector_radius")
tmp[0] = diameter - MXBCM_PARS["beam"]["x"]
tmp[1] = diameter - MXBCM_PARS["beam"]["y"]
tmp[2] = MXBCM_PARS["beam"]["x"]
tmp[3] = MXBCM_PARS["beam"]["y"]
return array_op("min", tmp)
}'
#%IU% ()
#%MDESC% Get the detector diameter.
def getMxDiameter() '{
return(2*getMxBcmPars("detector_radius"))
}'
#%IU% ()
#%MDESC% Get current filename (set by the detector macros).
def getMxCurrentFilename() '{
return MXCOLLECT_PARS["current_filename"]
}'
#%IU% ()
#%MDESC% Set current filename.
def setMxCurrentFilename(file) '{
setMxCollectPars("current_filename",file)
}'
#%IU% (dist)
#%MDESC%Calculate the resolution as function of the %B%dist%B% from the sample.
def CalculateResolutionFromDistance(dist) '{
local wavelength diameter radius ttheta resolution detdistmot tmp
wavelength = getMxWavelength()
radius = _getRadius()
if (radius == 0) {
return(0)
}
distance = dist == 0 ? A[motor_num(getMxSpecPars("detdistmot"))] : dist
ttheta = atan( radius / distance )
resolution = wavelength/(2*sin(ttheta/2))
return(resolution)
}'
#%IU% (resol)
#%MDESC% Calculate the distance from the sample as function of the %B%resol%B%.
def CalculateDistanceFromResolution(resol) '{
local wavelength ttheta radius distance resolution
# should we take the current resolution or the resolution asked for?
resolution = resol == 0 ? A[res] : resol
wavelength = getMxWavelength()
ttheta = 2*asin(wavelength/(2*resolution))
radius = _getRadius()
distance = radius / tan(ttheta)
return(distance)
}'
#%IU% ()
#%MDESC% Get current Beam centre for X.
def getMxBeamCentreX() '{
beam_centre_update()
return MXBCM_PARS["beam"]["x"]
}'
#%IU% ()
#%MDESC% Get current Beam Centre Y.
def getMxBeamCentreY() '{
beam_centre_update()
return MXBCM_PARS["beam"]["y"]
}'
def getMxUndulatorGap(which) '{
local gap key
key = sprintf("/beamline_pars/BCM_PARS/undulator[%d]", which)
gap = -1
if (xml_read("/mxlocal", sprintf("%s/device_uri", key)) >= 0) {
local out[]
esrf_io(XML_tmp[0]["__value__"], "DevReadSigValues", out)
if (xml_read("/mxlocal", sprintf("%s/gap_index", key)) >= 0) {
gap = out[XML_tmp[0]["__value__"]]
}
}
return gap
}'
def getMxUndulatorType(which) '{
local type key
key = sprintf("/beamline_pars/BCM_PARS/undulator[%d]", which)
type = ""
if (xml_read("/mxlocal", sprintf("%s/type", key)) >= 0) {
type = XML_tmp[0]["__value__"]
}
return type
}'
def getMxKappaValue() '{
global KAPPA_IN_USE
motpos = -9999
if (KAPPA_IN_USE == 1) {
get_angles
#kappamot = motor_num(MXBCM_PARS["kappaSpecMne"])
#if (kappamot != -1) {
# motpos = A[kappamot]
#}
motpos = A[kap1]
}
return motpos
}'
def getMxPhiValue() '{
get_angles
return A[phi]
# global KAPPA_IN_USE
# motpos = -1
# if (KAPPA_IN_USE == 1) {
# phimot = motor_num(MXBCM_PARS["phiSpecMne"])
# if (phimot != -1) {
# motpos = A[phimot]
# }
# }
# }
# return motpos
}'
def getMxKappaPhiValue() '{
if (getMxOscillationAxisName() == "Omega") {
return A[kap2]
} else {
return -9999
}
}'
def getMxOscillationAxisName() '{
if ((KAPPA_IN_USE == 1) && (fabs(getMxKappaValue()) < 1E6)) {
return "Omega"
} else {
return "Phi"
}
}'
def getMxSlitGapHorizontal() '{
local x1 x2 xs
getangles
x1=A[motor_num(MXSPEC_PARS["slits"]["s1h"])]
x2=A[motor_num(MXSPEC_PARS["slits"]["s2h"])]
if (x2<x1) {
xs = x2
} else {
xs = x1
}
return (xs)
}'
def getMxSlitGapVertical() '{
local y1 y2 ys
getangles
y1=A[motor_num(MXSPEC_PARS["slits"]["s1v"])]
y2=A[motor_num(MXSPEC_PARS["slits"]["s2v"])]
if (y2<y1) {
ys = y2
} else {
ys = y1
}
return(ys)
}'
cdef ("local_get_beamsize","","_beamsize")
def getMxBeamSizeX(dont_get_beamsize) '{
local slit_size
local ret
if (! dont_get_beamsize) {
local_get_beamsize
}
if (MXSPEC_PARS["beamsize"]["x"] > 0) {
if ((MXSPEC_PARS["beamsize"]["max_hor"]>0) && (MXSPEC_PARS["beamsize"]["x"] > MXSPEC_PARS["beamsize"]["max_hor"])) {
ret = MXSPEC_PARS["beamsize"]["max_hor"]
} else {
ret = MXSPEC_PARS["beamsize"]["x"]
}
if (ret > 1) {
# we are in microns, ISPyB wants millimeters
return ret/1000.0
} else {
return ret
}
} else {
slit_size = getMxSlitGapHorizontal()
if (slit_size <= MXSPEC_PARS["beamsize"]["max_hor"]) {
return slit_size
} else {
return MXSPEC_PARS["beamsize"]["max_hor"]
}
}
}'
def getMxBeamInfo() '{
return ["size_x": getMxBeamSizeX(), "size_y": getMxBeamSizeY(1), "shape": getMxBeamShape(1)]
}'
def getMxBeamSizeY(dont_get_beamsize) '{
local slit_size
local ret
if (! dont_get_beamsize) {
local_get_beamsize
}
if (MXSPEC_PARS["beamsize"]["y"] > 0) {
if ((MXSPEC_PARS["beamsize"]["max_ver"]>0) && (MXSPEC_PARS["beamsize"]["y"] > MXSPEC_PARS["beamsize"]["max_ver"])) {
ret = MXSPEC_PARS["beamsize"]["max_ver"]
} else {
ret = MXSPEC_PARS["beamsize"]["y"]
}
if (ret > 1) {
# we are in microns, ISPyB wants millimeters
return ret/1000.0
} else {
return ret
}
} else {
slit_size = getMxSlitGapVertical()
if (slit_size <= MXSPEC_PARS["beamsize"]["max_ver"]) {
return slit_size
} else {
return MXSPEC_PARS["beamsize"]["max_ver"]
}
}
}'
cdef ("local_get_totals","","_totals")
def getMxTotalParams() '{
MXCOLLECT_PARS["tot_exposure_time"] = 0
MXCOLLECT_PARS["tot_range"] = 0
local_get_totals
if (MXCOLLECT_PARS["tot_exposure_time"] == 0) {
MXCOLLECT_PARS["tot_exposure_time"] = \
(COLLECT_SEQ["exposure_time"] + 0.003)*COLLECT_SEQ["number_of_images"]
}
if (MXCOLLECT_PARS["tot_range"] == 0) {
MXCOLLECT_PARS["tot_range"] = \
COLLECT_SEQ["range"]*COLLECT_SEQ["number_of_images"]
}
}'
#%UU% ()
#%MDESC% calculate the latest beam centre given the current detector distance
def beam_centre_update() '{
global MXSPEC_PARS MXBCM_PARS
local AXBeam AYBeam BXBeam BYBeam XBeam YBeam
AXBeam = MXSPEC_PARS["beam"]["ax"]
AYBeam = MXSPEC_PARS["beam"]["ay"]
BXBeam = MXSPEC_PARS["beam"]["bx"]
BYBeam = MXSPEC_PARS["beam"]["by"]
if ( !(AXBeam == 0 || BXBeam == 0 )) {
# Calculate correct X and Y beam position to be put into the header
get_angles
XBeam = (AXBeam * A[motor_num(MXSPEC_PARS["detdistmot"])]) + BXBeam
YBeam = (AYBeam * A[motor_num(MXSPEC_PARS["detdistmot"])]) + BYBeam
} else {
egui_logmsg(sprintf("Warning:The beam centre is NOT calibrated, one of AXBeam (%6.6f),BXBeam (%6.2f),AYBeam (%6.6f),BYBeam (%6.2f) are 0",AXBeam,BXBeam,AYBeam,BYBeam))
return -1
}
# These variables can be used by other spec macros, so update them
MXBCM_PARS["beam"]["x"]=XBeam
MXBCM_PARS["beam"]["y"]=YBeam
if (XBeam == 0 || YBeam == 0) {
egui_logmsg("One or both of the beam centre parameters are 0")
return -1
}
return 1
}'
#%UU% ()
#%MDESC% Initialise the MXCOLLECT_PARS, MXBCM_PARS and MXSPEC_PARS with the
#default values (generic and beamline specific).
def pars_init() '{
# common parameters go here, local parameters go in mxlocal
# so far I do not know any common parameters...
# not even the detector distance motor name.
local_pars_init()
beam_centre_update()
}'
def local_pars_init() '{
if (xml_read("/mxlocal", "/beamline_pars") != 0) {
printf("Could not read MX local beamline parameters in file %s:\n -> %s\n", "/mxlocal", XML_tmp["__error__"])
exit
}
local tmp[] tmp2[] i n
n = split(XML_tmp[0]["__children__"], tmp)
for (i=0;i<n;i++) {
split(tmp[i], tmp2, ":")
_mxlocal_read_pars(sprintf("MX%s", tmp2[0]), tmp2[1])
}
# I do not like very much the following :
MXBCM_PARS["maximum_exposure"]= MXSPEC_PARS["maximum_counts"] * \
MXSPEC_PARS["intensity_calibration_constant"] * \
getMxCurrentTransmission()
# save original beam shape (from XML file)
MXBCM_PARS["original_beam_shape"]=MXBCM_PARS["beam_shape"]
}'
def _mxlocal_read_pars(name, path) '{
local tmp0[] k name2
unglobal @name
global @name[]
name2 = sprintf("_%s", name)
unglobal @name2
global @name2
if (xml_readProperties("/mxlocal", path) >= 0) {
tmp0=asso_keys(XML_tmp)
for (k in tmp0) {
@name[k] = XML_tmp[k]["__value__"]
@name2[k] = XML_tmp[k]["__path__"]
}
}
if (xml_read("/mxlocal", path) != 0) {
printf("Could not read parameters under %s:\n -> %s\n", path, XML_tmp["__error__"])
return
}
local tmp[] tmp2[] i childnamee childpathh
n = split(XML_tmp[0]["__children__"], tmp)
for (i=0;i<n;i++) {
split(tmp[i], tmp2, ":")
childname = tmp2[0]
childpath = tmp2[1]
if (!(childname in @name)) {
if (xml_readProperties("/mxlocal", childpath) != 0) {
printf("Could not read parameters under %s:\n -> %s\n", childpath, XML_tmp["__error__"])
return
}
tmp0 = asso_keys(XML_tmp)
for (k in tmp0) {
@name[childname][k]=XML_tmp[k]["__value__"]
@name2[childname][k]=XML_tmp[k]["__path__"]
}
}
}
}'
def local_pars_commit() '{
local tmp[] tmp2[] i n name name2
if (xml_read("/mxlocal", "/beamline_pars") != 0) {
printf("Could not read MX local beamline parameters in file %s:\n -> %s\n", "/mxlocal", XML_tmp["__error__"])
exit
}
n = split(XML_tmp[0]["__children__"], tmp)
for (i=0;i<n;i++) {
split(tmp[i], tmp2, ":")
name = sprintf("MX%s", tmp2[0])
name2 = sprintf("_MX%s", tmp2[0])
if ((whatis(name)&0x05)&&(whatis(name2)&0x05)) {
for (k in @name) {
xml_cache_write("/mxlocal", @name2[k], @name[k])
}
}
}
xml_do_write()
}'
def check_beam() '{
local countdown
if ((countdown = mi_refilltime()) != -1) {
if (countdown < 300) {
print "beam checking: next refill in less than 5 minutes, aborting"
egui_fatal("beam checking: next refill in less than 5 minutes, aborting")
exit
}
} else {
egui_logmsg("WARNING: COULD NOT CHECK FOR BEAM, CANNOT COMMUNICATE WITH FRONTEND DEVICE SERVER")
printf("WARNING: COULD NOT CHECK FOR BEAM, CANNOT COMMUNICATE WITH FRONTEND DEVICE SERVER\n")
return(-1)
}
return(0)
}'
#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% BLISS%BR%
#$Revision: 3.28 $ $Date: 2013/02/05 13:28:17 $%BR%
#%END%
#%LOG%
#$Log: mxutils.mac,v $
#Revision 3.28 2013/02/05 13:28:17 guijarro
#removed calls to getangles
#
#Revision 3.27 2012/05/11 07:31:27 witsch
#old macros still use esrf_io(FEIDDEV...
#
#_read_mach_current()
#
#called by check_beam()
#
#delete the first and make the second use mi_refilltime()
#
#Revision 1.25 2012/05/11 07:25:45 witsch
#old macros still use esrf_io(FEIDDEV...
#
#_read_mach_current()
#
#called by check_beam()
#
#delete the first and make the second use mi_refilltime()
#
#Revision 1.24 2011/02/25 18:54:17 guijarro
#added getMxBeamInfo() function, to get beam shape and size in one call
#
#Revision 1.23 2010/09/09 13:05:45 beteva
#added getMxTotalParams() to be used by the shutterless datacollection
#
#Revision 1.21 2010/03/29 07:45:40 guijarro
#added code for beamline parameters
#
#Revision 1.20 2010/02/09 15:52:40 blissadm
#do the right thing for undulator type and gaps
#
#Revision 1.19 2009/11/05 16:30:40 beteva
#changed getMxBeamSizeX and getMxBeamSizeY to cope with an aperture.
#
#Revision 1.18 2008/08/12 14:39:32 rey
#documentation changes
#
#Revision 1.17 2008/07/28 12:21:36 guijarro
#display fatal and log error messages in mxCuBE when check_beam fails
#
#Revision 1.16 2008/07/09 15:14:09 guijarro
#added functions to check for refill (check_beam() )
#
#Revision 1.15 2008/07/08 13:34:57 guijarro
#new getMxBeamSizeX and getMxBeamSizeY functions ;
#need a new 'beamsize' section in mxlocal.xml
#
#Revision 1.14 2008/05/22 13:42:06 guijarro
#added missing { }
#
#Revision 1.13 2008/04/29 14:27:15 gabadinh
#minor bug fix
#
#Revision 1.12 2008/04/16 12:56:19 gabadinh
#if no wavelength motor defined, tries to find the wavelength with the energy motor
#
#Revision 1.11 2008/04/15 08:54:51 spruce
#remove the check for aybeam and bybeam being 0 because if the beamlines
#are really well aligned it should be possible to have a 0 value
#
#Revision 1.10 2008/01/17 16:41:47 blissadm
#added halfcorner calculation, just in case we want to display it in mxcube
#
#Revision 1.8 2007/11/02 09:09:54 guijarro
#compatibility with beamlines with no undulators (like BM14)
#
#Revision 1.7 2007/10/03 13:19:30 spruce
#small bug fix
#
#Revision 1.6 2007/10/03 13:15:46 spruce
#*** empty log message ***
#
#Revision 1.5 2007/10/03 13:14:10 spruce
#added methods for 1.38 mxcollect.mac
#
#Revision 1.4 2006/09/26 12:46:27 spruce
#revise getDetectorBinningmode function
#
#Revision 1.3 2006/07/05 11:43:16 guijarro
#added local_pars_commit
#
#Revision 1.2 2006/07/04 12:55:49 guijarro
#added local_pars_init (reads mxlocal XML file, and creates associative arrays in Spec)
#
#Revision 1.1 2006/04/11 14:10:27 guijarro
#Initial revision
#
|