#============================================================================== # Macroname: auto.mac # ======== #+ # $Date: 2008/09/26 10:45:53 $ # $Author: schlepuetz $ # $Source: /cvs/G/SPEC/local/X04SA/ES3/auto.mac,v $ # $Revision: 1.7 $ # $Tag: $ # # Description This macro provides a set of definitions which allow for # automatic filter transmission and exposure time adjustments # during experiments. Type 'autohelp' for information on the # respective commands and their usage. # After each count command, the obtained counts are evaluated and # compared to four global threshold levels defining five # different ranges of count rates: Poor, Acceptable, Good, # Optimal, and Saturated. According to this analysis, filters and # optionally also the exposure time are adjusted automatically. # The general strategy to determine which action should be taken # is to optimize the speed of data aquisition, even at the # possible cost of a moderate reduction in signal-to-noise ratio. # Presently, only two distinct exposure times are supported, a # shorter one (t1) and a longer one (t2). # The actions taken are summarized in the following diagram: # # # Count rate | Threshold | Optimize only | Optimize filters and # Region | level | filters (Level 1) | exposure time (Level 2) # --------------------------------------------------------------------------- # Saturated | | decrease transm. | 1. decrease exptime # | | | 2. decrease tramsm. # ------------ TH4 -------------------------------------------------------- # Optimal | | - | 1. decrease exptime # | | | # ------------ TH3 -------------------------------------------------------- # Good | | increase tramsm. | 1. decrease exptime (>=1s) # | | | 2. increse transm. # ------------ TH2 = 1.5* ------------------------------------------------- # Acceptable | (t2/t1)*TH1 | increase tramsm. | 1. increase transm. # | | | (no change in exptime) # ------------ TH1 --------------------------------------------------------- # Poor | | increase tramsm. | 1. increase trams. # | | | 2. increase exptime # --------------------------------------------------------------------------- # # Note: In the "Good" region, the expure time is decreased to t1 only # if t1 is >= 1s, otherwise a 1 second exposure time is used. # This macro is based on an earlier version by O. Bunk # and R. Herger # # Author: C. M. Schlepuetz (CS) # Co-author(s): R. Herger (RH), P. R. Willmott (PW) # Address: Surface Diffraction Station # Materials Science Beamline X04SA # Swiss Light Source (SLS) # Paul Scherrer Institut # CH - 5232 Villigen PSI # Created: 2005/07/12 # #- # Chained macro definitions affected by this macro: # ------------------------------------------------- # # - user_prescan_head # - user_chk_counts # provided in the modified 'count' command in site_f.mac # - user_precount # # Change Log: # ----------- # # 2005/07/12 (CS): # - created first version of this file. # # 2005/12/12 (CS): # - implemented 4th threshold level to make exposure time control independent # of the dynamic range of a given detector or the filter transmission # adjustments. # - added globals AUTO_THRESH4, AUTO_THRESH4_COUNT # # 2006/03/03 (CS): # - improved the documentation and comments of this macro. # - fixed typo in autoInit. # # 2008/03/19 (CS): # - removed quotation marks around argument variables $1,$2 in autoSetLevel and # autoSetExposure, allowing one to also pass the arguments via variables. # - added autoShowExposure. # # 2008/09/26 (CS): # - replaced hard-coded call to epics_put for the filter transmissions by # actually calling the corresponding filter macro 'filterTrans'. # #============================================================================== # global AUTO_MAC # AUTO_MAC = DOFILE # Save the name of this macro file. # (Used for the help function). #+ #============================================================================== # This macro file contains the following commands: #- # #+ #------------------------------------------------------------------------------ # autohelp - generates this help text. This is obtained by # displaying the file auto.txt, which should sit in the # same directory as this macro file. #- # allow for misspelled help commands def helpauto 'autohelp' def helpAuto 'autohelp' def autoHelp 'autohelp' def autohelp '{ # ======== unix (sprintf ("dirname %s", AUTO_MAC), _1) ll = length (_1) if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1)) file = sprintf ("%s/auto.txt", _1) if (file_info (file, "-e")) { unix (sprintf ("cat %s | less", file)) } else { printf("\n Macros available in file auto.mac ($Revision: 1.7 $):\n") printf( " ========"\n) printf("\n") printf(" autohelp - creates this help text\n") printf(" autoSetLevel - activate or deactivate automatic filter\n") printf(" and exposure setting\n") printf(" autoSetExposure - define the short and long exposure time\n") printf(" used in case of automatic exposure\n") printf(" setting\n") printf(" autoShow - display current automatic filter settings\n") printf(" autoShowExposure - display current exposure time settings\n") } }' # INTERNAL ROUTINE #------------------------------------------------------------------------------ # autoInit - initializes important global variables. # # Usage : autoInit (should be called in site.mac) #- def autoInit '{ # ======== global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 global AUTO_THRESH1_COUNT, AUTO_THRESH2_COUNT global AUTO_THRESH3_COUNT, AUTO_THRESH4_COUNT # for safety, set the thresh values gigantically high to start with AUTO_THRESH1=1e8; AUTO_THRESH2=1e9; AUTO_THRESH3=1e10; AUTO_THRESH4=1e11 # for safety, set the thresh values gigantically high to start with AUTO_THRESH1_COUNT=100; AUTO_THRESH2_COUNT=100; AUTO_THRESH3_COUNT=100 AUTO_THRESH4_COUNT=100 }' #+ #------------------------------------------------------------------------------ # autoSetLevel - sets the automatic filter and exposure settings. # # Usage : autoSetLevel [] # # can be: # 0 - automatic filter and exposure OFF # 1 - automatic filter ON, automatic exposure OFF # 2 - automatic filter and exposure ON # optionally specifies the number of retries # before giving up (default = 20) # # example : autoSetLevel 2 15 # automatic filter and exposure ON, # 15 retries to optimize. #- def autosetlevel 'autoSetLevel' def autoSetLevel '{ # ============ global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 global AUTO_THRESH1_COUNT, AUTO_THRESH2_COUNT global AUTO_THRESH3_COUNT, AUTO_THRESH4_COUNT if (!(($#==1) || ($#==2)) || !(($1==0) || ($1==1) || ($1==2))) { eprint "Wrong number or illegal arguments in \'autoSetLevel\'" eprint "Usage:" eprint " autoSetLevel []" eprint "" eprint " can be:" eprint "0 - OFF" eprint "1 - only automatic filter ON, automatic exposure OFF" eprint "2 - automatic filter and exposure ON" eprint "" eprint " optionally sets the maximum number retries" eprint "to optimize the settings (default = 20)" } else { AUTO_LEVEL = $1 if($#==2){ AUTO_RETRY_MAX = $2 } else{ AUTO_RETRY_MAX = 20 # default is 20 retries } } #----------------------------------------------------------- # initialize the important variables to some starting values #------------------------------------------- # define necessary chained macro definitions #------------------ def autoPrescanHead \' # =============== # if automatic filter setting is active start scan with very low # filter transmission if (AUTO_LEVEL > 0) { filterTrans 1e-10 } \' #-------------------- def autoUserChkCounts \' # ================= if (AUTO_LEVEL > 0) { # automatic filter and exposure setting (if activated) success = autoAdjustRedo() } \' #---------------- def autoPrecount2 \' # ============= # if automatic exposure setting is activated calculate exposure time autoCalcExposure() \' #-------------------------------------------- # include necessary chained macro definitions # depending on the current auto-level if (AUTO_LEVEL > 0){ # add autoPrescanHead to user_prescan_head cdef("user_prescan_head","autoPrescanHead; ","auto_prescan_head_key",\\ 0x10) # add autoUserChkCounts to user_chk_counts cdef("user_chk_counts","autoUserChkCounts; ","auto_user_chk_counts_key") } if(AUTO_LEVEL > 1){ # add autoPrecount2 to beginning of user_precount cdef("user_precount","autoPrecount2; ","aaa_auto_precount_key",\\ 0x10) } #--------------------------------------------- # remove unnecessary chained macro definitions # depending on the current auto-level # Note: chained macro definitions which are not currently defined # can be deleted without producing an error. if (AUTO_LEVEL < 2) { # remove autoPrecount2 from user_precount cdef("user_precount","","auto_precount_key","delete") } if (AUTO_LEVEL < 1) { # remove autoPrescanHead from user_prescan_head cdef("user_prescan_head","","auto_prescan_head_key","delete") # remove autoUserChkCounts from user_chk_counts cdef("user_chk_counts","","auto_user_chk_counts_key","delete") } autoShow }' #+ #------------------------------------------------------------------------------ # autoSetExposure - set the standard exposure times used in case of # automatic filter and exposure settings. # # Usage : autoSetExposure # where is the shorter and # the longer exposure time in seconds [s]. # # example : autoSetExposure 1 10 #- def autoSetExposure '{ # =============== global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 global AUTO_THRESH1_COUNT, AUTO_THRESH2_COUNT global AUTO_THRESH3_COUNT, AUTO_THRESH4_COUNT if ($# != 2) { if (($# != 1)) { eprint "Wrong number or illegal arguments in \'autoSetExposure\'" eprint "Usage:" eprint "autoSetExposure " eprint "defines the short and long exposure times in seconds" eprint "(used if auto-level is set to 2 with \'autoSetLevel\')" } } else { AUTO_EXP_LO = $1 AUTO_EXP_HI = $2 } if (AUTO_EXP_LO >= AUTO_EXP_HI) { AUTO_EXP_LO = 1 AUTO_EXP_HI = 10 eprint ">> Invalid values - set to default values <<" } autoShowExposure # set AUTO_TRESH2 1.5 times higher than ratio of counting times to avoid # oscillations AUTO_THRESH2 = AUTO_THRESH1 * (AUTO_EXP_HI/AUTO_EXP_LO) * 1.5 }' #+ #------------------------------------------------------------------------------ # autoShow - show the auto-level settings. #- def autoInfo 'autoShow' def autoshow 'autoShow' def autoShow '{ # ======== #--------------------------------------------------- # inform the user on the currently active auto-level if (AUTO_LEVEL == 0) { printf("auto-level has been set to %d.\n", AUTO_LEVEL) printf("Automatic filter setting is OFF.\n") printf("Automatic exposure setting is OFF.\n") } else if (AUTO_LEVEL == 1) { printf("auto-level has been set to %d.\n", AUTO_LEVEL) printf("Automatic filter setting is ON.\n") printf("Automatic exposure setting is OFF.\n") } else if (AUTO_LEVEL == 2) { printf("auto-level has been set to %d.\n", AUTO_LEVEL) printf("Automatic filter setting is ON.\n") printf("Automatic exposure setting is ON.\n") } else { AUTO_LEVEL = 0 printf(">> Unknown auto-level - resetting to %d <<", AUTO_LEVEL) printf("Automatic filter setting is OFF.\n") printf("Automatic exposure setting is OFF.\n") } if(AUTO_LEVEL>1){ autoShowExposure } if(((whatis("IMAGE_IS_ON") & 0x08000000) != 0) && (IMAGE_IS_ON == 1)){ imageShow } }' #+ #------------------------------------------------------------------------------ # autoShowExposure - show the auto-level exposure settings. #- def autoShowExposure '{ # ================ printf("detector exposure times: short = %d s, long = %d s\n",\\ AUTO_EXP_LO,AUTO_EXP_HI) }' # Internal routine #------------------------------------------------------------------------------ # autoCalcExposure() - If automatic exposure setting is activated round the # current SPEC COUNT_TIME to either low or high exposure. # def autoCalcExposure() '{ # ================= global COUNT_TIME global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 global AUTO_THRESH1_COUNT, AUTO_THRESH2_COUNT global AUTO_THRESH3_COUNT, AUTO_THRESH4_COUNT if (AUTO_LEVEL == 2) { if (COUNT_TIME <= 0.5*(AUTO_EXP_LO+AUTO_EXP_HI)) { COUNT_TIME = AUTO_EXP_LO } else { COUNT_TIME = AUTO_EXP_HI } } return (COUNT_TIME) }' # Internal routine #------------------------------------------------------------------------------ # autoAdjust() - automatically adjusts the filter transmission and # exposure time of the currently active detector to obtain # the best possible signal level. # The function returns 1 if transmission or exposure # time are changed, 0 otherwise. # This routine should be performed after the counting # process (this is usually done by autoAdjustRedo() ). # Internal routine. # # Note: For area detectors, the background is not subtracted since over- # and under-exposure have to be avoided on an absolute scale. # def autoAdjust() '{ # ============ global COUNT_TIME global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 global AUTO_THRESH1_COUNT, AUTO_THRESH2_COUNT global AUTO_THRESH3_COUNT, AUTO_THRESH4_COUNT local autoAdjusted local autoExposure local autoTransmVal # do nothing when auto-level is zero if (AUTO_LEVEL < 1) { return(0) } # set exposure times to default if they are not defined yet if (AUTO_EXP_LO < 0.0000001) { AUTO_EXP_LO = 1 } if (AUTO_EXP_HI < 0.0000001) { AUTO_EXP_HI = 10 } autoAdjusted = 0 autoExposure = autoCalcExposure() autoTransmVal = epics_get("X04SA-ES2-FI:TRANSM") # try to set filters and exposure time if (AUTO_THRESH4_COUNT > 2) { # intensity too high -> reduce exposure time or filter transmission if ((AUTO_LEVEL >= 2) && (autoExposure > AUTO_EXP_LO)) { autoExposure = AUTO_EXP_LO printf("Intensity too high - setting exposure to %d sec\n",\\ autoExposure) } else { autoTransmVal /= 10.0 filterTrans autoTransmVal printf("Intensity too high, reducing transmission to %.3e\n",\\ epics_get("X04SA-ES2-FI:TRANSM")) } autoAdjusted = 1 } if (AUTO_THRESH2_COUNT < 1) { # intensity too low -> take out filter or increase exposure time if (autoTransmVal < 1.0) { # take out filter if (autoTransmVal < 1e-10) { autoTransmVal = epics_get("X04SA-ES2-FI:TRANSM") } autoTransmVal *= 10.0 if (AUTO_THRESH1_COUNT < 1) { autoTransmVal *= 5.0 } # readjust transmission-soll if it is > 1 now. if (autoTransmVal > 1.0) { autoTransmVal = 1.0 } filterTrans autoTransmVal printf("Intensity too low, increasing transmission to %.3e\n",\\ epics_get("X04SA-ES2-FI:TRANSM")) autoAdjusted = 1 } else { # increase exposure time? if ((AUTO_LEVEL >= 2) && (autoExposure < AUTO_EXP_HI)) { # check for long exposure-time if (AUTO_THRESH1_COUNT < 1) { autoExposure = AUTO_EXP_HI autoAdjusted = 1 printf("Intensity too low - setting exposure to %d sec\n",\\ autoExposure) } } } } if ((AUTO_THRESH3_COUNT < 1) && (AUTO_THRESH2_COUNT > 1)){ # decrease exptime? if ((AUTO_LEVEL >= 2) && (autoExposure > AUTO_EXP_LO)) { autoExposure = AUTO_EXP_LO if (autoExposure < 1){ autoExposure = 1 } if (autoExposure != COUNT_TIME){ autoAdjusted = 1 printf("High intensity - setting exposure to %d sec\n",\\ autoExposure) } } else { # increase transmission ? if (autoTransmVal < 1.0) { # take out filter if (autoTransmVal < 1e-10) { autoTransmVal = epics_get("X04SA-ES2-FI:TRANSM") } autoTransmVal *= 10.0 # readjust transmission-soll if it is > 1 now. if (autoTransmVal > 1.0) { autoTransmVal = 1.0 } filterTrans autoTransmVal printf("Intensity too low, increasing transmission to %.3e\n",\\ epics_get("X04SA-ES2-FI:TRANSM")) autoAdjusted = 1 } } } if ((AUTO_THRESH4_COUNT < 1) && (AUTO_THRESH3_COUNT > 1)){ # decrease exptime? if ((AUTO_LEVEL >= 2) && (autoExposure > AUTO_EXP_LO)) { autoExposure = AUTO_EXP_LO autoAdjusted = 1 printf("High intensity - setting exposure to %d sec\n",\\ autoExposure) autoAdjusted = 1 } } if (AUTO_LEVEL == 2) { AUTO_COUNT_TIME = autoExposure COUNT_TIME = AUTO_COUNT_TIME _ctime = AUTO_COUNT_TIME # set the counting time for a scan to # AUTO_COUNT_TIME } return(autoAdjusted) }' # Internal routine #------------------------------------------------------------------------------ # autoAdjustRedo() - determines whether auto-adjusting has been successful. # If not, counting is repeated until the best possible # filter and exposure settings have been obtained. # This routine is performed after the counting process # (in user_count_end). # Internal routine. # # Note: This macro makes use of the 'recount' macro which has been added to # site.mac. # def autoAdjustRedo() '{ # ================ global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 global AUTO_THRESH1_COUNT, AUTO_THRESH2_COUNT global AUTO_THRESH3_COUNT, AUTO_THRESH4_COUNT local retryCount local redo local _success _success = 1 if (AUTO_LEVEL < 1) { return(_success) } else { retryCount = 0 redo = 1 while (redo != 0) { redo = 0 retryCount++ if (autoAdjust() != 0) { if (retryCount < AUTO_RETRY_MAX) { redo = 1 } else { eprint " >> Couldn\'t optimize filter and exposure settings. <<" } } if (redo != 0) { # repeat exposure recount COUNT_TIME } else { _success = 1 redo = 0 } } return (_success) } }' #+ #------------------------------------------------------------------------------ #- #============================================================================== # ##################################################### # emacs setup: force text mode to get no help with # # indentation and force use of spaces # # when tabbing. # # Local Variables: # # mode:text # # indent-tabs-mode:nil # # End: # ##################################################### # # $Log: auto.mac,v $ # Revision 1.7 2008/09/26 10:45:53 schlepuetz # replaced hard-coded call to epics_put for the filter transmissions by actually calling the corresponding filter macro filterTrans # # Revision 1.6 2008/03/20 13:35:00 schlepuetz # removed quotation marks around argument variables , in autoSetLevel and autoSetExposure, added autoShowExposure. # # Revision 1.5 2007/01/22 15:13:01 maden # *** empty log message *** # # Revision 1.4 2006/03/03 10:07:40 schlepuetz # improved the documentation, fixed typo in autoInit. # # Revision 1.3 2006/03/02 16:30:10 schlepuetz # some more documentation - to be completed... # # Revision 1.2 2006/03/01 13:02:46 maden # Check-in newer version from /work ... # # Revision 1.1 2005/11/10 10:24:45 schlepuetz # first tested version of this file # # # #============================= End of $RCSfile: auto.mac,v $ ===