esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%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) '{
	return((k/0.51242415)*(k/0.51242415))
}'


#%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)'{
	return(0.51242415*sqrt(delta_e_in_eV))
}'


#%UU%
#%MDESC%
#    Interactive definition of the kscan
def kscan_setup '{
    local i

    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

    array KSCAN_E [4000] KSCAN_T [4000]

    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)

    KSCAN_POST [0] [0] = KSCAN_POST [0] [0]

    KSCAN_N_POST = getval("Enter number of  post-edge regions ", KSCAN_N_POST)

    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])
    }

    _kscan_profile

}'


#%UU% <energy_motor> <edge_energy> <time>
#%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>"
        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.
    }

    KSCAN_TIME  = $3
    _kscan_profile
    print _ctime=KSCAN_T [0] * KSCAN_TIME

    _kscan
}'


#%IU% [parma]
#%MDESC%
#    This macro calculates a grid in energy and time for the spectrum
def _kscan_profile '{
    # This macro calculates a grid in energy and time for the spectrum
    local i j e_work k_work

    KSCAN_E [0] = KSCAN_E0 + KSCAN_PRE [0] [0]
    KSCAN_T [0] = KSCAN_PRE [0] [2]

    # pre-edge profile
    i=0
    for (j=0;j<KSCAN_N_PRE;j++) {
        if(j == KSCAN_N_PRE -1) {
            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]
        }
    }

    # edge profile
    KSCAN_E [i] = e_work
    KSCAN_T [i] = KSCAN_EDGE_T

    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 profile
    #? k_work = kscan_calcK(e_work - KSCAN_E0)
    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]
    }

    KSCAN_NPTS=i+1

    if ((substr(PSEUDOE_UNITS,0,2)=="EV") | (substr(PSEUDOE_UNITS,0,2)=="ev") | \
        (substr(PSEUDOE_UNITS,0,2)=="Ev") | (substr(PSEUDOE_UNITS,0,2)=="eV")) {

        # nothing...
    }
    else {
        for(i=0;i<KSCAN_NPTS;i++){
            KSCAN_E [i] = KSCAN_E [i]/1000.0
        }
    }

    printf("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)
	_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

    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%