esrf

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


#%TITLE% fluoXAS.mac
#%NAME%
#
#%CATEGORY%
#%DESCRIPTION%
#  XANES or EXAFS with fluo mapping
#%EXAMPLE%
#%DL%
#%DT%XXXsetup%DD%
#%SETUP%
#%UL%
#%LI%
#%XUL%

global fXAS_PAR[]


######################################################################
###############################         ##############################
###############################  SETUP  ##############################
###############################         ##############################
######################################################################

need spec_utils
need hg

hg_generate("fXAS")

#%IU%
#%MDESC%
#
def fXAS_setup_id21 '{

    # -saving directory
    # -name of the scan
#    fXAS_setup_saving  /data/id21/inhouse/16jan/sxm_restart/   saphir_xrf_ff

    # motors
    fXAS_setup_motors sampy sampz enmono

    fXAS_PAR["start_offset"] = 0.03

    # map : zapimage parameters.
    # to be filled from grab values  or "centered node" from GUI
    #               Ystart Yend    Ypoints    Zstart Zend     Zpoints   FluoIntTime(ms)
    fXAS_setup_map  40      50     10         54     64       10        50

    # for acquisition : saves all standard ZAP counters.

    # for h5 generation : use these counters only
    fXAS_setup_counters  ROI_I0  ROI_It

    # E0 E1 E2 ... En  in keV
    fXAS_setup_energy_boundaries   4.950      4.97      4.99      5     5.1

    # energy resolutions in eV
    fXAS_setup_energy_resolutions          5      3        1       20

    fXAS_PAR["scan_number"] = 0
    fXAS_PAR["previous_radix"] = "radix_Undefined"

    fXAS_msg("can use fXAS_info to display info")

}'


#%IU%
#%MDESC%
#
def fXAS_setup_id16 '{

    # -saving directory
    # -name of the scan
#    fXAS_setup_saving  /data/id21/inhouse/16jan/sxm_restart/   saphir_xrf_ff

    #                 <fast_motor_mne> <slow_motor_mne> <energy_motor_mne>
    fXAS_setup_motors  sampy            sampz            energy


    # for mono backlash
    fXAS_PAR["start_offset"] = 0.03

    # map : zapimage parameters.
    # to be filled from grab values  or "centered node" from GUI
    #               Ystart Yend    Ypoints    Zstart Zend     Zpoints   FluoIntTime(ms)
    #               FAST                      SLOW
    fXAS_setup_map  40      50     10         54     64       10        50

    # for acquisition : saves all standard ZAP counters.

    # for h5 generation : use these counters only
    fXAS_setup_counters  ROI_I0  ROI_It

    #############  ROCKING CURVE ############3
    #                    <first_rc_motor>  <second_rc_motor>
    fXAS_setup_rc_motors  pb2               pt2

    # Selection of counter to use for rocking curve
    fXAS_setup_zap_rc_counter zap_p201_It
#    fXAS_setup_zap_rc_counter zap_p201_IC
#    fXAS_setup_zap_rc_counter zap_p201_I0

    # Performs a rocking curve of piezo pb2 BEFORE each energy move.
    # (ie Before esk correction)
    # fXAS_setup_zap_rc_off
    fXAS_setup_zap_rc_on

    # E0 E1 E2 ... En  in keV
    fXAS_setup_energy_boundaries      17.35    17.45    17.47    17.5
    # energy resolutions in eV
    fXAS_setup_energy_resolutions           5        1        5
    fXAS_setup_energy_resolutions           40        8        10

    fXAS_PAR["scan_number"] = 0
    fXAS_PAR["previous_radix"] = "radix_Undefined"

    fXAS_msg("You can use fXAS_info : to display config info")
    fXAS_msg("            fXAS_scan_info : to display SCAN info")
}'


#%UU%
#%MDESC%
#    <fast_motor_mne> <slow_motor_mne> <energy_motor_mne>
def fXAS_setup_motors '{
     global fXAS_PAR[]

     local _nb_param
    _nb_param = $#

    if (_nb_param == 3){

        # TODO : check motors.

        # Y zappable motor
        fXAS_PAR["fast_motor_mne"] = "$1"

        # Z motor
        fXAS_PAR["slow_motor_mne"] = "$2"

        #  energy motor mne
        fXAS_PAR["energy_motor_mne"] = "$3"

        # fXAS_PAR["mode"] = "centered" | "grab"
    }
    else{
        printf("$0 usage : \n")
        printf("          $0 <fast_motor_mne> <slow_motor_mne> <energy_motor_mne>\n")
    }
}'


#%UU%
#%MDESC%
# Defines counter to use for rocking curve(s)
def fXAS_setup_zap_rc_counter '{
    local _nb_param
    _nb_param = $#

    if (_nb_param ==1){
        fXAS_PAR["rc_counter"] = "$1"
    }
    else{
        printf("usage : $0 <counter_mne>")
    }
}'


#%UU%
#%MDESC%
#      <rc_motor1>   [<rc_motor2>]
#  1 or 2 zappable motors
def fXAS_setup_rc_motors '{
     global fXAS_PAR[]

     local _nb_param
    _nb_param = $#

    if (_nb_param == 1){
        # TODO : check motors.  : motor_is_zappable(mot_mne)

        # rocking curve zappable motor 1
        fXAS_PAR["rc_motor1_mne"] = "$1"

        fXAS_PAR["rc_motor_number"] = 1
    }

    if (_nb_param == 2){
        # TODO : check motors.

        # rocking curve zappable motor 1
        fXAS_PAR["rc_motor1_mne"] = "$1"

        # rocking curve zappable motor 2
        fXAS_PAR["rc_motor2_mne"] = "$2"

        fXAS_PAR["rc_motor_number"] = 2
    }

    if (_nb_param == 0 || _nb_param >2){
        printf("$0 usage : \n")
        printf("          $0   <rc_motor1> [<rc_motor2>] \n")
    }
}'


# map : zapimage parameters.
# to be filled from grab values  or "centered node" from GUI
#               Ystart Yend  Ypoints    Zstart Zend   Zpoints   FluoIntTime
# fXAS_setup_map  49.3   65.4  40         105.1  121.2  60        50
def fXAS_setup_map '{
    local _nb_param

    _nb_param = $#

    if (_nb_param == 7){
        fXAS_PAR["Ystart"]  = "$1"
        fXAS_PAR["Yend"]    = "$2"
        fXAS_PAR["Ypoints"] = "$3"

        fXAS_PAR["Zstart"]  = "$4"
        fXAS_PAR["Zend"]    = "$5"
        fXAS_PAR["Zpoints"] = "$6"

        fXAS_PAR["FluoIntTime"] = "$7"
    }
    else{
        printf("$0 usage : \n")
        printf("        $0 <Ystart> <Yend>  <Ypoints>    <Zstart> <Zend>   <Zpoints>   <FluoIntTime>")
    }
}'


# ???
def fXAS_setup_counters '{
    local _nb_param  _nb_fields
    local  _params[]

    _nb_param = $#

    _nb_fields = split("$*", _params)
    if (_nb_fields != _nb_param){
        fXAS_err("fXAS_setup_counters: Oh oh error in param analysis ???")
    }

    fXAS_PAR["RoiCounterNumber"] = _nb_fields

    for (ii in _params ){
        # print _params[ii]
        fXAS_PAR["RoiCounter"][ii] = _params[ii]
    }
}'


# E0 E1 E2 ... En   *in keV*
# fXAS_setup_energy_boundaries   3.1    3.5     3.6    3.7   4.0
def fXAS_setup_energy_boundaries '{
    local _nb_param  _nb_fields
    local _pars[] _params[]

    _nb_param = $#

    _nb_fields = split("$*", _pars)
    if (_nb_fields != _nb_param){
        printf("ERROR : fXAS_setup_energy_boundaries: Oh oh error in param analysis ???")
    }

    _params = ass_arr_revrse(_pars)

    if (!ass_arr_is_ordered(_params)){
#%IU%
#%MDESC%
        print "ERROR : fXAS_setup_energy_boundaries: Energies values must be ordered !!"
        print _params
    }
    else{
        fXAS_PAR["Eboundaries_number"] = _nb_fields
        for (ii in _params ){
            # print _params[ii]
            fXAS_PAR["Eboundarie"][ii] = _params[ii]
        }
    }
}'


# energy resolutions  *in eV*
#fXAS_setup_energy_resolutions       5      0.5      1     2
def fXAS_setup_energy_resolutions '{
    local _nb_param  _nb_fields
    local _pars[] _params[]

    _nb_param = $#
    _nb_fields = split("$*", _pars)
    if (_nb_fields != _nb_param){
        printf("ERROR : fXAS_setup_energy_resolutions: Oh oh error in param analysis ???")
    }

    _params = ass_arr_revrse(_pars)

    fXAS_PAR["Eresolution_number"] = _nb_fields
    if (fXAS_PAR["Eresolution_number"] != (fXAS_PAR["Eboundaries_number"]-1)){
        printf("ERROR : fXAS_setup_energy_resolutions : number of energie resolutions is not good\n")
        print _params
    }
    else{
        for (ii in _params ){
            fXAS_PAR["Eresolution"][ii] = _params[ii]
        }
    }
}'


def fXAS_setup_zap_rc_on '{
    fXAS_PAR["rc_active"] = 1
}'

def fXAS_setup_zap_rc_off '{
    fXAS_PAR["rc_active"] = 0
}'

######################################################################
###############################         ##############################
###############################  INFOS  ##############################
###############################         ##############################
######################################################################


def fXAS_info '{

    printf("---------------  Fluo XAS configuration  --------------\n")

    fXAS_show_motors
    fXAS_show_rc
    fXAS_show_map_param
    fXAS_show_counters
    fXAS_show_boundaries
    fXAS_show_resolutions

    printf("-------------------------------------------------------\n")
    printf("-------------------------------------------------------\n")

}'


def fXAS_show_motors '{
    printf("\n-------- Motors --------\n")
    printf(" fast_motor_mne = %s \n", fXAS_PAR["fast_motor_mne"])
    printf(" slow_motor_mne = %s \n", fXAS_PAR["slow_motor_mne"])
    printf(" energy_motor_mne = %s \n", fXAS_PAR["energy_motor_mne"])

}'

def fXAS_show_rc '{
    local ii

    printf("\n-------- Rocking Curve --------\n")

    printf(" rocking curve active : ")
    cprint_yes_no( fXAS_PAR["rc_active"])
    print ""

    printf(" rocking curve counter : \"%s\"\n" , fXAS_PAR["rc_counter"])

    if (fXAS_PAR["rc_motor_number"] > 0){
        printf(" rc mot 1 = \"%s\" \n", fXAS_PAR["rc_motor1_mne"])
    }

    if (fXAS_PAR["rc_motor_number"] == 2){
        printf(" rc mot 2 = \"%s\" \n", fXAS_PAR["rc_motor2_mne"])
    }
}'

def fXAS_show_map_param '{
    printf("\n-------- Mapping --------\n")
    printf(" Ystart  = %s \n", fXAS_PAR["Ystart"] )
    printf(" Yend    = %s \n", fXAS_PAR["Yend"]   )
    printf(" Ypoints = %s \n", fXAS_PAR["Ypoints"])
    print ""
    printf(" Zstart  = %s \n", fXAS_PAR["Zstart"] )
    printf(" Zend    = %s \n", fXAS_PAR["Zend"]   )
    printf(" Zpoints = %s \n", fXAS_PAR["Zpoints"])
    print ""
    printf(" FluoIntTime = %s ms\n", fXAS_PAR["FluoIntTime"])

}'

def fXAS_show_counters '{
    local ii

    printf("\n-------- Counters --------\n")
    printf(" Number of Counters: %d \n", fXAS_PAR["RoiCounterNumber"])

    for (ii=0 ; ii < fXAS_PAR["RoiCounterNumber"]; ii++){
        printf(" Counter #%d : %g  \n", ii, fXAS_PAR["RoiCounterNumber"][ii])
    }
}'

def fXAS_show_boundaries '{
    local ii

    printf("\n-------- Energy boundaries --------\n")
    printf(" Number of regions: %d  (boundaries: %d) \n",               \
           fXAS_PAR["Eboundaries_number"]-1, fXAS_PAR["Eboundaries_number"])

    for (ii=0 ; ii<fXAS_PAR["Eboundaries_number"]; ii++){
        printf(" Energy bounradie #%d : %g  keV\n", ii, fXAS_PAR["Eboundarie"][ii])
    }

}'


def fXAS_show_resolutions '{
    local ii

    printf("\n-------- Energy resolutions --------\n")
    printf(" Number of regions: %d  \n",    fXAS_PAR["Eresolution_number"])

    for (ii=0 ; ii<fXAS_PAR["Eresolution_number"]; ii++){
        printf(" Energy resolution for region #%d : %g eV \n", ii, fXAS_PAR["Eresolution"][ii])
    }

}'


######################################################################
###############################        ###############################
###############################  SCAN  ###############################
###############################        ###############################
######################################################################


# zapimage with fluo detector
#
#
def fXAS_scan '{
    _fXAS_scan(1)
}'

# Prints regions
def fXAS_scan_info '{
    _fXAS_scan(0)
}'

def _fXAS_scan(execute) '{
    local _zap_cmd
    local _emin  _emax  _eres
    local _epoint_cmd
    local ii ee
    local _starting_mono_position _mono_start_cmd  _start_cmd
    local _e_num  _e_num_total  _tot_nb_points

    if (execute){
        zapmusstmcaoff
        zapxmapon
    }

    #### Creation of a new sub directory to save images.
    # Tests for radix change.
    if (ZAP_TOOLS["radix"] != fXAS_PAR["previous_radix"]){
        fXAS_PAR["scan_number"] = 0
        fXAS_PAR["previous_radix"] = ZAP_TOOLS["radix"]
    }

    # Save current zap directory to restore it later
    fXAS_PAR["old_dir"] = ZAP_TOOLS["dir"]

    # Name of the new zap directory
    fXAS_PAR["dir"] = sprintf("%s/%s_fluoXAS_%d" , ZAP_TOOLS["dir"], ZAP_TOOLS["radix"], fXAS_PAR["scan_number"])

    cdef("cleanup_once", ";_fXAS_cleanup;", "_fXAS_scan_", 0x20)

    # Searches for a non existing directory.
    if(file_info(fXAS_PAR["dir"], "isdir")){
        printf( "directory %s already exists...\nsearching for a new one...\n", fXAS_PAR["dir"])
    }
    while(file_info(fXAS_PAR["dir"], "isdir")) {
        fXAS_PAR["scan_number"]++
        fXAS_PAR["dir"] = sprintf("%s/%s_fluoXAS_%d" , ZAP_TOOLS["dir"], ZAP_TOOLS["radix"], fXAS_PAR["scan_number"])
    }

    # Naming of rocking curves dir and files.
    fXAS_PAR["rc_dir"] = sprintf("%s/rocking_curves" , fXAS_PAR["dir"])
    fXAS_PAR["rc_radix1"] = sprintf("%s_%s_rock_curve" , ZAP_TOOLS["radix"], fXAS_PAR["rc_motor1_mne"])
    fXAS_PAR["rc_radix2"] = sprintf("%s_%s_rock_curve" , ZAP_TOOLS["radix"], fXAS_PAR["rc_motor2_mne"])
    printf( "I will use : %s \n", fXAS_PAR["dir"])
    printf( "I will use RC : %s \n", fXAS_PAR["rc_dir"])

    if (execute){
        # Creates new directory.
        fXAS_msg(sprintf ("Creating directory \"%s\"", fXAS_PAR["dir"]))
        fXAS_msg(sprintf ("Creating directory \"%s\"", fXAS_PAR["rc_dir"]))

        unix(sprintf("mkdir -p %s", fXAS_PAR["dir"]))
        unix(sprintf("mkdir -p %s", fXAS_PAR["rc_dir"]))

        # Set new directory for ZAP.
        ZAP_TOOLS["dir"]   = fXAS_PAR["dir"]
        #ZAP_TOOLS["radix"] = zs_radix
        ZAP_TOOLS["radix"] = sprintf("%s_fluoXAS_%d" , ZAP_TOOLS["radix"], fXAS_PAR["scan_number"])
        user_zap_file_update
    }

    # Moves mono <start_offset> eV below starting energy to avoid backlash error.
    _starting_mono_position = fXAS_PAR["Eboundarie"]["0"] - fXAS_PAR["start_offset"]
    _mono_start_cmd = sprintf("moveE %g",  _starting_mono_position)

    # Moves to starting energy. (mvr to avoid backlash etc.)
    _start_cmd = sprintf("mvr %s %g", fXAS_PAR["energy_motor_mne"], fXAS_PAR["start_offset"])

    if(execute){
        eval(_start_cmd)

        print _mono_start_cmd
        eval(_mono_start_cmd)
    }
    else{
        print _start_cmd
        print _mono_start_cmd
    }

    # Calculated total number of points:
    _tot_nb_points = 0
    for (ii=0; ii< fXAS_PAR["Eresolution_number"] ; ii++){
        _emin = fXAS_PAR["Eboundarie"][ii]
        _emax = fXAS_PAR["Eboundarie"][ii+1]
        _eres = fXAS_PAR["Eresolution"][ii] / 1000

        _nb_points_region = (_emax - _emin ) / _eres

        # printf("_nb_points_region %d = %20.20f \n", ii, _nb_points_region)
        # print "_nb_points_region - round_down(_nb_points_region, 1)=", _nb_points_region - round_down(_nb_points_region, 1)
        if (fabs(_nb_points_region - round_down(_nb_points_region, 1)) < 0.00001) {
            #
            fXAS_PAR["NBpointsRegion"][ii] = round_up(_nb_points_region,1) -1
        }
        else{
            fXAS_PAR["NBpointsRegion"][ii] = round_up(_nb_points_region,1)
        }
        _tot_nb_points += fXAS_PAR["NBpointsRegion"][ii]
    }
    print "calculated number of points : " _tot_nb_points

    # Loop over regions.
    for (ii=0; ii< fXAS_PAR["Eresolution_number"] ; ii++){
        printf ("region %d \n", ii)
        _e_num = 0
        _emin = fXAS_PAR["Eboundarie"][ii]
        _emax = fXAS_PAR["Eboundarie"][ii+1]
        _eres = fXAS_PAR["Eresolution"][ii] / 1000

        if (_eres == 0){
            printf("ERROR : fXAS : _eres == 0 \n")
            fXAS_PAR["NBpointsRegion"][ii] = 1
        }
        else{
            fXAS_PAR["NBpointsRegion"][ii] = round_up((_emax - _emin ) /  _eres, 1)
        }

        printf ("  Emin=%g Emax=%g  Eres=%g  Nbpoints=%d \n",           \
                _emin, _emax, _eres, fXAS_PAR["NBpointsRegion"][ii])

        # Loop over energies of region ii.
        for (ee=_emin ; (_emax-ee)>0.00001;  ee+= _eres){

            # Relative moves between energy points (rather than
            # absolute moveE) to avoid backlashes and variability of
            # intervals.
            _epoint_cmd = sprintf("mvr %s %g", fXAS_PAR["energy_motor_mne"],  _eres)

            if(execute){
                printf("***** fXAS ******** energy %d/%d in region %d \n" , _e_num, fXAS_PAR["NBpointsRegion"][ii], ii)
                printf("***** fXAS ******** energy %d/%d in total \n" , _e_num_total, _tot_nb_points)
                eval(_epoint_cmd)
                printf("  E cmd= %s\n", _epoint_cmd)
            }
            else{
                printf("  %s", ee)
            }

            _zap_cmd = sprintf("zapimage %s %g %g %d  %s %g %g %d  %g 0", \
                               fXAS_PAR["fast_motor_mne"],              \
                               fXAS_PAR["Ystart"], fXAS_PAR["Yend"] , fXAS_PAR["Ypoints"], \
                               fXAS_PAR["slow_motor_mne"] ,             \
                               fXAS_PAR["Zstart"], fXAS_PAR["Zend"] , fXAS_PAR["Zpoints"], \
                               fXAS_PAR["FluoIntTime"] )


            if(execute){
                # zapimage sampy 49  31 36 sampz 54 72.5 37  fXAS_PAR["integration_time"]   0
                printf( "  _zap_cmd =%s ", _zap_cmd)
                eval(_zap_cmd)

                if(fXAS_PAR["rc_active"] == 1){
                    # Performs rocking curve(s) on 1 or 2 motors.
                    fXAS_rocking_curve()
                }
            }

            _e_num++
            _e_num_total++
        }

        if(!execute){
            printf( "\n  _zap_cmd =%s \n", _zap_cmd)
        }
    }

    printf("total number of points : %d  (pre-calculated : %d)\n", _e_num_total , _tot_nb_points)
    if (_e_num_total != _tot_nb_points){
        cprint_red("ohhh ohhh error in point number pre calculation ??? " )
    }

    # Restore...
    cdef("cleanup_once", "", "_fXAS_scan_", "delete")
    _fXAS_cleanup
}'


# Performs rocking curve(s) on 1 or 2 motors.
def fXAS_rocking_curve() '{
    local _plotsel_cmd
    local _zap_rc1_cmd _zap_rc2_cmd

    # Changes saving dir before RC.
    ZAP_TOOLS["dir"]   = fXAS_PAR["rc_dir"]
    fXAS_PAR["rc_restore_radix"] = ZAP_TOOLS["radix"]

    # ??? empty on id16
    user_zap_file_update

    # Selects RC counter for zap.
    _plotsel_cmd = sprintf("zapplotselect 0 1  %s pos", fXAS_PAR["rc_counter"])
    print _plotsel_cmd
    eval(_plotsel_cmd)
    ZAP_PLOT["plot1D"] = 1
    ZAP_PLOT["plot2D"] = 0

    # First rocking curve.
    if (fXAS_PAR["rc_motor_number"] > 0){
        ZAP_TOOLS["radix"] = fXAS_PAR["rc_radix1"]
        ZAP_TOOLS["numim"]--
        printf("First rocking curve on %s.\n", fXAS_PAR["rc_motor1_mne"])
        _zap_rc1_cmd = sprintf(" dzapline %s -2 2 30 200", fXAS_PAR["rc_motor1_mne"])
        print _zap_rc1_cmd
        eval(_zap_rc1_cmd)
        cen
    }

    # Second rocking curve.
    if (fXAS_PAR["rc_motor_number"] == 2){
        ZAP_TOOLS["radix"] = fXAS_PAR["rc_radix2"]
        ZAP_TOOLS["numim"]--

        printf("Second rocking curve on %s.\n", fXAS_PAR["rc_motor2_mne"])
        _zap_rc2_cmd = sprintf(" dzapline %s -5 5 30 200", fXAS_PAR["rc_motor2_mne"])
        print _zap_rc2_cmd
        eval(_zap_rc2_cmd)
        pic
    }

    # Restores ZAP saving dir after RC.
    ZAP_TOOLS["dir"]   = fXAS_PAR["dir"]
    ZAP_TOOLS["radix"] = fXAS_PAR["rc_restore_radix"]

    # ??? empty on id16
    user_zap_file_update
}'


def _fXAS_cleanup '{

    print "-------------------------_fXAS_cleanup   no Ctrl-C -------------------------"
    # Restores directory for ZAP.
    ZAP_TOOLS["dir"]   = fXAS_PAR["old_dir"]
    ZAP_TOOLS["radix"] = fXAS_PAR["previous_radix"]

    # ZAP_TOOLS["numim"] = ???

    user_zap_file_update

    # motors ???
}'


#%MACROS%
#%IMACROS%
#%TOC%
#%DEPENDENCIES%
#%AUTHOR%
#%END%