#%TITLE% KSCAN.MAC
#%NAME%
# Macros to perform scans on K.
#%DESCRIPTION%
# This macro set allows to make scans in energy with several
# regions around an edge.
# Each region can have different spacing between points as
# well as to have different collection time per region.
#%SETUP%
# A pseudo motor energy has to be available.
# By default a set of parameters is given. This set of parameters
# can be implemented by a call to the macro *kscan_defaults*.
# Otherways the parameters can be changed by calling to *kscan_setup*.
#%USAGE%
#
# kscan <mot> <ene> <>
#
#%EXAMPLE%
#
# kscan energy_motor 7.111 2
#
# Performs a kscan of the motor energy_motor whith 7.111 taken as
# the edge energy (all parameters in kscan are referred to the edge
# position in order to allow a single profile to be used at different
# edges).
#%END%
need spec_utils
#%UU%(<k>)
#%MDESC%
# Given a value of k, returns the corresponding value in energy above
# the edge in eV.
def kscan_calcE(k) '{
# what is this 0.51242415 ???
return( pow( (k/0.51242415), 2 ) )
}'
#%UU%(<delta_e_in_eV>)
#%MDESC%
# Given a value of the energy (in eV above the edge) as input, returns
# the corresponding value in k.
def kscan_calcK(delta_e_in_eV)'{
# what is this 0.51242415 ???
return(0.51242415 * sqrt(delta_e_in_eV))
}'
#%UU%
#%MDESC%
# Interactive definition of the energy regions.
def kscan_setup '{
local i
global KSCAN_N_PRE KSCAN_N_POST # numbers of pre/post regions.
global KSCAN_PRE KSCAN_POST
global KSCAN_EDGE_1 KSCAN_EDGE_2 KSCAN_EDGE_INC KSCAN_EDGE_T KSCAN_EDGE_K
global KSCAN_E0
global KSCAN_NPTS
global KSCAN_TIME # time factor
# energy regions table
global array KSCAN_E[4000]
# time regions table
global array KSCAN_T[4000]
#### Definition of PRE-egde regions.
KSCAN_N_PRE = getval("Enter number of pre-edge regions ", KSCAN_N_PRE)
KSCAN_PRE[0][0] = KSCAN_PRE[0][0]
for (i=0 ; i<KSCAN_N_PRE ; i++){
printf("Defining pre-edge region %i\n", i+1)
KSCAN_PRE [i] [0] = getval("Enter energy relative to edge (in eV)", KSCAN_PRE [i] [0])
KSCAN_PRE [i] [1] = getval("Enter energy increment (in eV)", KSCAN_PRE [i] [1])
KSCAN_PRE [i] [2] = getval("Enter collection time in seconds", KSCAN_PRE [i] [2])
}
KSCAN_EDGE_1 = getval("Enter starting edge region energy (in eV relative to edge):", KSCAN_EDGE_1)
KSCAN_EDGE_2 = getval("Enter final edge region energy (in eV relative to edge):", KSCAN_EDGE_2)
KSCAN_EDGE_INC = getval("Enter energy increment in edge region:", KSCAN_EDGE_INC)
KSCAN_EDGE_T = getval("Enter collection time in seconds:", KSCAN_EDGE_T)
KSCAN_EDGE_K = kscan_calcK(KSCAN_EDGE_2)
#### Definition of POST-egde regions.
KSCAN_N_POST = getval("Enter number of post-edge regions ", KSCAN_N_POST)
KSCAN_POST[0][0] = KSCAN_POST[0][0]
printf("Your edge region ends at k = %f \n", KSCAN_EDGE_K)
for (i=0 ; i<KSCAN_N_POST ; i++){
printf("Defining post-edge region %i\n", i+1)
KSCAN_POST [i] [0] = getval("Enter k end", KSCAN_POST [i] [0])
KSCAN_POST [i] [1] = getval("Enter k increment", KSCAN_POST [i] [1])
KSCAN_POST [i] [2] = getval("Enter collection time in seconds", KSCAN_POST [i] [2])
}
}'
#%UU% <energy_motor> <edge_energy> <time_factor>
#%MDESC%
# Executes the scan defined with kscan_setup or kscan_defaults.
# The time is a multiplicative factor to apply to the time defined
# in kscan_setup.
#
def kscan '{
if ($# != 3) {
print "Usage: kscan <energy_motor> <edge_energy> <time_factor>"
exit
}
if (motor_valid("$1")){
_m[0] = motor_num("$1")
}
else{
print "Invalid motor name: " "$1"
exit
}
_nm = 1
HEADING = sprintf("$0 $*")
KSCAN_E0 = $2
# Make sure we work in eV.
if(KSCAN_E0 < 100) {
KSCAN_E0 = KSCAN_E0 * 1000.
}
# time factor.
KSCAN_TIME = $3
# Profile calculations.
_kscan_profile
_ctime = KSCAN_T [0] * KSCAN_TIME
print "_ctime = " _ctime
_kscan
}'
#%IU%
#%MDESC%
# Calculates a grid in energy and time for the spectrum.
#
def _kscan_profile '{
local i j e_work k_work
# First point.
KSCAN_E [0] = KSCAN_E0 + KSCAN_PRE [0] [0]
KSCAN_T [0] = KSCAN_PRE [0] [2]
#### PRE-edge regions profiles.
i=0
for (j=0 ; j < KSCAN_N_PRE ; j++) {
if(j == KSCAN_N_PRE -1) {
# -> Last of PRE-edge regions.
# KSCAN_EDGE_1 should be negative.
e_work = KSCAN_E0 + KSCAN_EDGE_1
}
else {
e_work = KSCAN_E0 + KSCAN_PRE[j+1][0]
}
while (KSCAN_E [i] < e_work) {
i++
KSCAN_E [i] = KSCAN_E [i-1] + KSCAN_PRE [j] [1]
KSCAN_T [i] = KSCAN_PRE [j] [2]
}
}
#### K-edge region profile.
KSCAN_E [i] = e_work
KSCAN_T [i] = KSCAN_EDGE_T # Acquisition time in EDGE region
e_work = KSCAN_E0 + KSCAN_EDGE_2
while (KSCAN_E [i] < e_work) {
i++
KSCAN_E [i] = KSCAN_E [i-1] + KSCAN_EDGE_INC
KSCAN_T [i] = KSCAN_EDGE_T
}
KSCAN_E [i] = e_work
KSCAN_T [i] = KSCAN_EDGE_T
# ?
k_work = kscan_calcK(e_work - KSCAN_E0)
#### POST-edge profile.
for (j=0 ; j<KSCAN_N_POST ; j++) {
# ??? k_work = kscan_calcK(e_work - KSCAN_E0)
while (k_work < KSCAN_POST [j] [0]) {
i++
# ?
k_work += KSCAN_POST [j] [1]
KSCAN_E [i] = KSCAN_E0 + kscan_calcE(k_work)
KSCAN_T [i] = KSCAN_POST [j] [2]
}
e_work = KSCAN_E [i]
}
# Total number of points of the scan.
KSCAN_NPTS = i+1
# ? Converts energies into keV if needed ?
if (toupper(substr(PSEUDOE_UNITS, 0, 2)) == "EV") {
# nothing...
}
else {
for(i=0 ; i<KSCAN_NPTS ; i++){
KSCAN_E [i] = KSCAN_E [i]/1000.0
}
}
printf("KSCAN : This scan has %g points with %g seconds scanning time ", \
KSCAN_NPTS, array_op("cols", KSCAN_T))
printf("and likely takes %g (2sec deadtime) \n", \
array_op("cols", KSCAN_T) + KSCAN_NPTS*2 )
}'
#%IU% [parma]
#%MDESC%
#
def _kscan '{
local i
for (i=0 ; i<_nm ; i++) {
_bad_lim = 0
_chk_lim _m[i] KSCAN_E[0]
_chk_lim _m[i] KSCAN_E[KSCAN_NPTS-1]
if (_bad_lim) exit;
}
}
# _n1++
_n1=KSCAN_NPTS
_cols=_nm+_hkl_col
X_L = motor_name(_m[0])
Y_L = cnt_name(DET)
# start / finish
_s[0] = KSCAN_E [0]
_f[0] = KSCAN_E [KSCAN_NPTS-1]
_sx = _s[0]
_fx = _f[0]
FPRNT=PPRNT=VPRNT=""
{
local i
for (i=0;i<_nm;i++) {
FPRNT=sprintf("%s%s ",FPRNT,motor_name(_m[i]))
PPRNT=sprintf("%s%8.8s ",PPRNT,motor_name(_m[i]))
VPRNT=sprintf("%s%9.9s ",VPRNT,motor_name(_m[i]))
}
}
FPRNT=sprintf("%s%s ",FPRNT,_hkl_sym1)
scan_head
PFMT=sprintf("%%s%%8.%df ",UP)
VFMT=sprintf("%%s%%9.%df ",UP)
def _scan_on \'
for(;NPTS < KSCAN_NPTS;NPTS++) {
local i
#
A[_m[0]] = KSCAN_E [NPTS]
scan_move
FPRNT=PPRNT=VPRNT=""
for (i=0;i<_nm;i++) {
FPRNT=sprintf("%s%.8g ", FPRNT, A[_m[i]])
PPRNT=sprintf(PFMT, PPRNT, A[_m[i]])
VPRNT=sprintf(VFMT, VPRNT, A[_m[i]])
}
FPRNT=sprintf("%s%s ", FPRNT, _hkl_val)
#
_ctime = KSCAN_T[NPTS] * KSCAN_TIME
scan_loop
# data_nput(PL_G, NPTS, A[_m[0]]*UN, S[DET])
scan_data(NPTS, A[_m[0]])
scan_plot
}
scan_tail
\'
_scan_on
'
#%UU%
#%MDESC%
# This macro sets a profile as default. This profile should be good
# for most of the applications. The profile can always be visualized
# and/or changed with kscan_defaults.
#
def kscan_defaults '{
global KSCAN_N_PRE KSCAN_N_POST
global KSCAN_PRE KSCAN_POST
global KSCAN_EDGE_1 KSCAN_EDGE_2 KSCAN_EDGE_INC KSCAN_EDGE_T KSCAN_EDGE_K
global KSCAN_E0
global KSCAN_NPTS KSCAN_TIME
global array KSCAN_E [4000] KSCAN_T [4000]
KSCAN_N_PRE = 2
KSCAN_N_POST = 1
KSCAN_PRE [0] [0] = -100.0
KSCAN_PRE [0] [1] = 5.0
KSCAN_PRE [0] [2] = 1.0
KSCAN_PRE [1] [0] = -50.0
KSCAN_PRE [1] [1] = 2.0
KSCAN_PRE [1] [2] = 1.0
KSCAN_EDGE_1 = -20
KSCAN_EDGE_2 = +20
KSCAN_EDGE_INC = 0.5
KSCAN_EDGE_T = 1
KSCAN_POST [0] [0] = 16.0
KSCAN_POST [0] [1] = 0.03
KSCAN_POST [0] [2] = 1
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% V.A.Sole - ID26 - ESRF - Copyright 1999
#%TOC%
|