#============================================================================== # 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 #auto_set_level - activate or deactivate automatic filter and exposure setting #auto_set_exposure - define the short and long exposure time used in case of automatic exposure setting #auto_show - display current automatic filter settings\n") #auto_show_xposure - display current exposure time settings\n") #============================================================================== def auto_init(): 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 auto_init() def auto_set_level(auto_level, max_tries = 20): """ 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) """ global AUTO_LEVEL global AUTO_RETRY_MAX AUTO_LEVEL = auto_level AUTO_RETRY_MAX = max_tries # Callbacks def auto_prescan_head(): if (AUTO_LEVEL > 0): filter_trans (1e-10) # if automatic filter setting is active start scan with very lowfilter transmission def auto_user_chk_counts(): if (AUTO_LEVEL > 0): success = auto_adjust_redo() # automatic filter and exposure setting (if activated) def auto_precount_2() auto_calc_exposure() # if automatic exposure setting is activated calculate exposure time 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) if (AUTO_LEVEL < 2): 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") auto_show() def auto_set_exposure(short_exp, long_exp) """ 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]. """ global AUTO_EXP_LO, AUTO_EXP_HI global AUTO_THRESH1, AUTO_THRESH2, AUTO_THRESH3, AUTO_THRESH4 AUTO_EXP_LO = short_exp AUTO_EXP_HI = long_exp if (AUTO_EXP_LO >= AUTO_EXP_HI): AUTO_EXP_LO = 1 AUTO_EXP_HI = 10 print ">> Invalid auto_set_exposure values - set to default values <<" auto_show_exposure() # 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 def auto_show(): """ show the auto-level settings. inform the user on the currently active auto-level """ if (AUTO_LEVEL == 0): print("auto-level has been set to %d.\n" % AUTO_LEVEL) print("Automatic filter setting is OFF.\n") print("Automatic exposure setting is OFF.\n") elif (AUTO_LEVEL == 1): print("auto-level has been set to %d.\n" % AUTO_LEVEL) print("Automatic filter setting is ON.\n") print("Automatic exposure setting is OFF.\n") elif (AUTO_LEVEL == 2): print("auto-level has been set to %d.\n" % AUTO_LEVEL) print("Automatic filter setting is ON.\n") print("Automatic exposure setting is ON.\n") else: AUTO_LEVEL = 0 print(">> Unknown auto-level - resetting to %d <<"% AUTO_LEVEL) print("Automatic filter setting is OFF.\n") print("Automatic exposure setting is OFF.\n") if(AUTO_LEVEL>1): auto_show_exposure() #TODO: if Image being sampled, show it #if(((whatis("IMAGE_IS_ON") & 0x08000000) != 0) && (IMAGE_IS_ON == 1)){ # image_show() def auto_show_exposure(): """ show the auto-level exposure settings. """ print("detector exposure times: short = %d s, long = %d s\n" % (AUTO_EXP_LO,AUTO_EXP_HI)) def auto_calc_exposure(): #If automatic exposure setting is activated round the current SPEC COUNT_TIME to either low or high exposure. global COUNT_TIME global AUTO_LEVEL global AUTO_EXP_LO, AUTO_EXP_HI 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 def autoAdjust(): # 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. 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 if (AUTO_LEVEL < 1): return(0) # do nothing when auto-level is zero # 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 = auto_calc_exposure() autoTransmVal = caget("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 print("Intensity too high - setting exposure to %d sec\n"% autoExposure) else: autoTransmVal /= 10.0 filterTrans autoTransmVal print("Intensity too high, reducing transmission to %.3e\n" % caget("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 = caget("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 filter_trans (autoTransmVal) print("Intensity too low, increasing transmission to %.3e\n"% caget("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 print("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 print("High intensity - setting exposure to %d sec\n" % autoExposure) else: # increase transmission ? if (autoTransmVal < 1.0): # take out filter if (autoTransmVal < 1e-10): autoTransmVal = caget("X04SA-ES2-FI:TRANSM") autoTransmVal *= 10.0 # readjust transmission-soll if it is > 1 now. if (autoTransmVal > 1.0): autoTransmVal = 1.0 filterTrans autoTransmVal print("Intensity too low, increasing transmission to %.3e\n" % caget("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 print("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 return autoAdjusted def auto_adjust_redo(): # 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. global AUTO_LEVEL global AUTO_RETRY_MAX global AUTO_COUNT_TIME _success = 1 if (AUTO_LEVEL < 1): return(_success) 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): recount COUNT_TIME else: _success = 1 redo = 0 return (_success)