diff --git a/config/devices.properties b/config/devices.properties index 4bf545d..86bbcac 100644 --- a/config/devices.properties +++ b/config/devices.properties @@ -41,4 +41,4 @@ oa=ch.psi.pshell.epics.Motor|X04SA-ES3-XPS:OMEGAA|||true #sixch=ch.psi.pshell.device.MotorGroupBase|alpha delta gamma omegaH nu phi||| fourcv=ch.psi.pshell.device.MotorGroupBase|alpha delta gamma omegaV||| $energy=ch.psi.pshell.epics.Positioner|X04SA-DCM:E X04SA-DCM:E-READ|||true -transm=ch.psi.pshell.epics.ControlledVariable|X04SA-ES2-FI:TRANSM-SET X04SA-ES2-FI:TRANSM||| +transm=ch.psi.pshell.epics.ControlledVariable|X04SA-ES2-FI:TRANSM-SET X04SA-ES2-FI:TRANSM|||true diff --git a/devices/transm.properties b/devices/transm.properties new file mode 100644 index 0000000..cd54776 --- /dev/null +++ b/devices/transm.properties @@ -0,0 +1,8 @@ +#Thu Oct 18 17:36:38 CEST 2018 +maxValue=1.0 +minValue=0.0 +offset=0.0 +precision=5 +resolution=NaN +scale=1.0 +unit= diff --git a/script/spec/image.py b/script/spec/image.py new file mode 100644 index 0000000..a32e5fc --- /dev/null +++ b/script/spec/image.py @@ -0,0 +1,757 @@ +#============================================================================== +# Macroname: image.mac +# ========= +#+ +# $Date: 2008/03/20 13:36:14 $ +# $Author: schlepuetz $ +# $Source: /cvs/G/SPEC/local/X04SA/ES3/image.mac,v $ +# $Revision: 1.11 $ +# $Tag: $ +# +# Description: This macro file provides a set of macro definitions which are +# used to analyze images (taken by any sort of imaging device) +# on-line during data acquisition and return a set of charac- +# teristic values to SPEC. +# It is thus possible to plot results of a scan (usually an +# intensity value) during data acquisition with the imaging +# device, just like one would with a point detector. +# Furthermore, the image information can be used to automate +# filter transmission and exposure time settings during a scan +# (refer to auto.mac for more information on automated scans). +# +# Note: 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 Institute +# CH - 5232 Villigen PSI +# Created: 2005/07/12 +# +#- +# Chained macro definitions affected by this macro: +# ------------------------------------------------- +# - user_getcounts +# +# Change Log: +# ----------- +# +# 2005/07/12 (CS): +# - created first version of this file. +# +# 2005/12/10 (CS): +# - fixed bug in imageGetInt: background region area was not correctly +# calculated in the c-routine and consequently all intensities were wrong. +# (also changed the c-routine, of course) +# +# 2005/12/11 (CS): +# - attempt to generalize the image_get_int routine to images of different +# sizes and color-depths, and possibly header lengths. +# Introduced new globals variables: +# IMAGE_INFO_FILENAME +# IMAGE_HEADER_LENGTH (in bytes) +# IMAGE_COLOR_DEPTH (in number of bits, e.g. 16 or 32) +# - write an info-file with information about each image in imageUserGetcounts +# which can be accessed by all external programs which want to look at the +# images. +# - Increase the number of threshold levels for image analysis to 4. That way, +# the thresholds for adjusting the exposure time automatically (see also +# auto.mac) and the filter transmission are independent of each other. +# Introduced new global variables: +# IMAGE_THRESH4 +# IMAGE_THRESH4_COUNT +# +# 2006/01/27 (CS): +# - fixed typo in imageCheckRoi +# +# 2006/06/23 (CS): +# - retrieve IMAGE_PATH from IMAGE_FILENAME with unix command DIRNAME. +# - copy image information file into IMAGE_PATH such that it is accessible +# to all applications which have access to the image path. +# +# 2006/08/09 (CS): +# - input to 'imgeSetRoi' is now possible in several ways, including user +# interaction. +# - removed old commented out workarounds. +# +# 2006/09/21 (CS): +# - added new functionality to the image_get_int.c routine for selectively +# median filtering only those pixels where the measured intensity differs +# from the mean of the surrounding pixels by more than N times the standard +# deviation of these neighbours. N is presently set to 30 in imageGetInt. +# +# 2006/11/29 (CS): +# - include wait loop in imageUserGetcounts to make sure the image file is +# available an non-empty in order to do statistical analysis with +# image_get_int.c. +# +# 2007/04/05 (CS): +# - new error message if image file to be analyzed is not found. +# +# 2007/04/22 (CS): +# - changed imageCheckROI to allow for ROIs of 1 pixel width/height (used to +# be at least 2 pixels). +# +# 2008/03/19 (CS): +# - removed quotation marks around argument variables $1,$2 in imageSetRoi, +# allowing one to also pass the arguments via variables. +# - added imageShowRoi. +# +#============================================================================== +# + global IMAGE_MAC +# + IMAGE_MAC = DOFILE # Save the name of this macro file. + # (Used for the help function). +#+ +#============================================================================== +# This macro file contains the following commands: +#- +# +#+ +#------------------------------------------------------------------------------ +# imagehelp - generates this help text. This is obtained by +# displaying the file image.txt, which should sit in the +# same directory as this macro file. +#- + +# allow for misspelled help commands +def helpimage 'imagehelp' +def helpImage 'imagehelp' +def imageHelp 'imagehelp' + +def imagehelp '{ +# ========= + + unix (sprintf ("dirname %s", IMAGE_MAC), _1) + ll = length (_1) + if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1)) + file = sprintf ("%s/image.txt", _1) + if (file_info (file, "-e")) { + unix (sprintf ("cat %s | less", file)) + } else { + printf("\n Macros available in file image.mac ($Revision: 1.11 $):\n") + printf( " ========="\n) + printf("\n") + printf(" imagehelp - creates this help text\n") + printf(" imageOn - turn on image analysis functionality\n") + printf(" imageOff - turn off image analysis functionality\n") + printf(" imageShow - show current image analysis setup.\n") + printf(" imageShowRoi - show current region of interest info.\n") + printf(" imageSetRoi - define a signal and background region-\n") + printf(" of-interest (ROI).") + printf(" imageCheckRoi - checks whether ROI is valid and within\n") + printf(" image bounds. + printf(" imageGetInt - description\n") + + } +}' + +#+ +#------------------------------------------------------------------------------ +# imageInit - initializes all global variables used by image.mac +#- + +def imageInit '{ +# ========= + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + +}' + + +#+ +#------------------------------------------------------------------------------ +# imageOn - turn on macro functionality to analyze images acquired by +# an area detector on-line and return the results to SPEC. +#- + +def imageon 'imageOn' + +def imageOn '{ +# ======= + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + #-------------------------------------------- + # include necessary chained macro definitions + + #--------------------- + def imageUserGetcounts \' + # ================== + + if (IMAGE_IS_ON) { + + # update IMAGE_PATH variable + unix(sprintf("dirname %s",IMAGE_FILENAME), IMAGE_PATH) + + # write important image information to file so image_get_int.c and other + # possible helper applications can read it. + + local ux_cmd + ux_cmd = "" + IMAGE_INFO_FILENAME = "/tmp/spec_image_info.dat" + ux_cmd = sprintf("echo \"%s\" > %s",\\ + IMAGE_FILENAME, IMAGE_INFO_FILENAME) + if (unix(ux_cmd) != 0) { + eprint ">> Cannot store image information file <<" + } else { + ux_cmd = sprintf("echo \"%.6f\" >> %s",\\ + time(), IMAGE_INFO_FILENAME) + if (unix(ux_cmd) != 0) { + eprint ">> Cannot store image information file <<" + } + unix(sprintf("echo \"%d\" >> %s",\\ + IMAGE_HEADER_LENGTH,IMAGE_INFO_FILENAME)) + unix(sprintf("echo \"%d %d %d\" >> %s",\\ + IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH,\\ + IMAGE_INFO_FILENAME)) + unix(sprintf("echo \"%d %d %d %d\" >> %s",\\ + IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2, \\ + IMAGE_INFO_FILENAME)) + unix(sprintf("echo \"%d %d %d %d\" >> %s",\\ + IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2, \\ + IMAGE_INFO_FILENAME)) + } + + # copy information file into image path + unix(sprintf("cp -f %s %s", IMAGE_INFO_FILENAME, IMAGE_PATH)) + + # get the AUTO_THRESH2 value if auto levels are enabled + if ((whatis("AUTO_THRESH2") & 0x08000000) == 0) { + IMAGE_THRESH2=AUTO_THRESH2 + } + + # check whether image file is ready to be read (size > 0 bytes) + retry = 0 + _tmp_filename = IMAGE_FILENAME + while((!(file_info(_tmp_filename,"-s"))) & (retry<3000)){ + printf("waiting for image file %s\n",IMAGE_FILENAME) + printf("retry %d of 3000\n",retry) + retry++ + if (retry%100 == 0) { + unix(sprintf("head -n 1 %f", IMAGE_FILENAME)) + } + sleep(0.01) + } + + # get the integrated intensity in the intensity and background boxes + imageGetInt IMAGE_THRESH1 IMAGE_THRESH2 IMAGE_THRESH3 IMAGE_THRESH4 + + # update the auto-level threshold count values if auto-level support + # is available + if ((whatis("AUTO_THRESH1_COUNT") & 0x08000000) == 0) { + AUTO_THRESH1_COUNT=IMAGE_THRESH1_COUNT + AUTO_THRESH2_COUNT=IMAGE_THRESH2_COUNT + AUTO_THRESH3_COUNT=IMAGE_THRESH3_COUNT + AUTO_THRESH4_COUNT=IMAGE_THRESH4_COUNT + } + + # return the background corrected intensity + if (IMAGE_AREA_BG > 0){ + S[2] = (IMAGE_I_SUM - IMAGE_I_BG/IMAGE_AREA_BG*IMAGE_AREA_SIG) + } else{ + S[2] = IMAGE_I_SUM + } + + # correct for filter transmission and exposure time + # p epics_get("X04SA-ES2-FI:TRANSM") + S[3] = S[2] / COUNT_TIME / epics_get("X04SA-ES2-FI:TRANSM") + + # write plot information for Matlab + local ux_cmd, comFile, tmpFile + ux_cmd = "" + tmpFile = "/tmp/spec_image_temp.dat" + comFile = "/tmp/spec_matlab_image.dat" + ux_cmd = sprintf("echo \"%s\" > %s",\\ + IMAGE_FILENAME, tmpFile) + if (unix(ux_cmd) != 0) { + eprint ">> Can not store Matlab plot information <<" + } else { + ux_cmd = sprintf("echo \"%.6f\" >> %s",\\ + time(), tmpFile) + if (unix(ux_cmd) != 0) { + eprint ">> Can not store Matlab plot information <<" + } + unix(sprintf("echo \"%d %d\" >> %s",\\ + IMAGE_XDIM, IMAGE_YDIM, tmpFile)) + unix(sprintf("echo \"%d %d %d %d\" >> %s",\\ + IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2, tmpFile)) + unix(sprintf("echo \"%d %d %d %d\" >> %s",\\ + IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2, tmpFile)) + + # overwrite the last file + unix(sprintf("mv -f %s %s",tmpFile,comFile)) + } + } + \' + # add imageUserGetcounts to middle of user_getcounts + cdef("user_getcounts","imageUserGetcounts; ","image_user_getcounts_key") + + #--------------------------------------------------- + # update the global variables for auto-level support + + if ((whatis("AUTO_THRESH1") & 0x08000000) == 0) { + AUTO_THRESH1 = IMAGE_THRESH1 + AUTO_THRESH2 = IMAGE_THRESH2 + AUTO_THRESH3 = IMAGE_THRESH3 + AUTO_THRESH4 = IMAGE_THRESH4 + } + + IMAGE_IS_ON=1 + + imageShow + +}' + +#+ +#------------------------------------------------------------------------------ +# imageOff - turn off macro functionality to analyze images acquired by +# an area detector on-line and return the results to SPEC. +#- + +def imageoff 'imageOff' + +def imageOff '{ +# ======== + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + + #--------------------------------------------- + # remove unnecessary chained macro definitions + + # remove imageUserGetcounts from user_getcounts + cdef("user_getcounts","imageUserGetcounts; ","image_user_getcounts_key",\\ + "delete") + + IMAGE_IS_ON=0 + + imageShow + +}' + +#+ +#------------------------------------------------------------------------------ +# imageShow - show whether image analysis is currently enabled and +# display the region-of-interest (ROI) settings. +#- + +def imageshow 'imageShow' +def imageInfo 'imageShow' +def imageinfo 'imageShow' + +def imageShow '{ +# ========= + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + if(IMAGE_IS_ON==1){ + printf("\nImage analysis is currently enabled.\n") + printf("The active imaging device name is: %s\n", IMAGE_DEVICE) + imageShowRoi + } else{ + printf("Image analysis is disabled.\n") + } + +}' + +#+ +#------------------------------------------------------------------------------ +# imageShowRoi - show information on the currently active region of interest +#- + +def imageshowroi 'imageShowRoi' +def imageshowROI 'imageShowRoi' +def imageShowROI 'imageShowRoi' + +def imageShowRoi '{ +# ============ + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + imageCheckRoi + +}' + + +#+ +#------------------------------------------------------------------------------ +# imageSetRoi - set the region-of-interest for intensity and background +# integration. +# +# Usage : imageSetRoi +# prompts user for roi coordinates +# or imageSetRoi +# set signal roi to and use same +# coordinates for background roi +# (as a result, no background is subtracted) +# or imageSetRoi +# set signal roi to and background +# roi to . +#- + +def imagesetroi 'imageSetRoi' +def imageSetROI 'imageSetRoi' + +def imageSetRoi '{ +# =========== + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + if ($# == 8) { + IMAGE_SX1 = $1 + IMAGE_SY1 = $2 + IMAGE_SX2 = $3 + IMAGE_SY2 = $4 + IMAGE_BX1 = $5 + IMAGE_BY1 = $6 + IMAGE_BX2 = $7 + IMAGE_BY2 = $8 + } else if($# == 4){ + IMAGE_SX1 = $1 + IMAGE_SY1 = $2 + IMAGE_SX2 = $3 + IMAGE_SY2 = $4 + IMAGE_BX1 = $1 + IMAGE_BY1 = $2 + IMAGE_BX2 = $3 + IMAGE_BY2 = $4 + } else if($# == 0){ + sig_roi = getval("Signal Roi (sx1 sy1 sx2 sy2):",sprintf("%d %d %d %d",\ + IMAGE_SX1,IMAGE_SY1,IMAGE_SX2,IMAGE_SY2)) + sscanf(sig_roi,"%d %d %d %d",IMAGE_SX1,IMAGE_SY1,IMAGE_SX2,IMAGE_SY2) + bg_roi = getval("Background Roi (bx1 by1 bx2 by2):",sprintf("%d %d %d %d",\ + IMAGE_SX1,IMAGE_SY1,IMAGE_SX2,IMAGE_SY2)) + sscanf(bg_roi,"%d %d %d %d",IMAGE_BX1,IMAGE_BY1,IMAGE_BX2,IMAGE_BY2) + } else{ + eprint "Wrong number of arguments in \'imageSetRoi\'" + eprint "Usage:" + eprint " imageSetRoi" + eprint " prompts the user for input" + eprint " imageSetRoi " + eprint " set background roi = signal roi (no background subtraction)" + eprint " imageSetRoi " + eprint " sets signal and background roi individually" + exit + } + + imageCheckRoi + +}' + +#+ +#------------------------------------------------------------------------------ +# imageCheckRoi - Check the region of interest for intensity and background +# integration for consistency with the image dimensions, etc. +# +# Usage : imageCheckRoi # no arguments needed +#- + +def imageCheckRoi '{ +# ============= + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + local coordAdjusted + + coordAdjusted = 0 + + #----------------- + # check signal box + + if (IMAGE_SX1 < 1) { + IMAGE_SX1 = 1 + coordAdjusted = 1 + } + if (IMAGE_SY1 < 1) { + IMAGE_SY1 = 1 + coordAdjusted = 1 + } + if (IMAGE_SX1 > IMAGE_XDIM-1) { + IMAGE_SX1 = IMAGE_XDIM-1 + coordAdjusted = 1 + } + if (IMAGE_SY1 > IMAGE_YDIM-1) { + IMAGE_SY1 = IMAGE_YDIM-1 + coordAdjusted = 1 + } + if (IMAGE_SX2 > IMAGE_XDIM-1) { + IMAGE_SX2 = IMAGE_XDIM-1 + coordAdjusted = 1 + } + if (IMAGE_SY2 > IMAGE_YDIM-1) { + IMAGE_SY2 = IMAGE_YDIM-1 + coordAdjusted = 1 + } + if (IMAGE_SX2 < IMAGE_SX1) { + IMAGE_SX2 = IMAGE_SX1 + coordAdjusted = 1 + } + if (IMAGE_SY2 < IMAGE_SY1) { + IMAGE_SY2 = IMAGE_SY1 + coordAdjusted = 1 + } + + #--------------------- + # check background box + + if (IMAGE_BX1 < 1) { + IMAGE_BX1 = 1 + coordAdjusted = 1 + } + if (IMAGE_BY1 < 1) { + IMAGE_BY1 = 1 + coordAdjusted = 1 + } + if (IMAGE_BX1 > IMAGE_XDIM-1) { + IMAGE_BX1 = IMAGE_XDIM-1 + coordAdjusted = 1 + } + if (IMAGE_BY1 > IMAGE_YDIM-1) { + IMAGE_BY1 = IMAGE_YDIM-1 + coordAdjusted = 1 + } + if (IMAGE_BX2 > IMAGE_XDIM-1) { + IMAGE_BX2 = IMAGE_XDIM-1 + coordAdjusted = 1 + } + if (IMAGE_BY2 > IMAGE_YDIM-1) { + IMAGE_BY2 = IMAGE_YDIM-1 + coordAdjusted = 1 + } + if (IMAGE_BX2 < IMAGE_BX1) { + IMAGE_BX2 = IMAGE_BX1 + coordAdjusted = 1 + } + if (IMAGE_BY2 < IMAGE_BY1) { + IMAGE_BY2 = IMAGE_BY1 + coordAdjusted = 1 + } + + if (coordAdjusted != 0) { + eprint">> Coordinates out of range - automatically adjusted. <<" + } + printf("signal region of interest : (%3d,%3d) (%3d,%3d)\n",\\ + IMAGE_SX1,IMAGE_SY1,IMAGE_SX2,IMAGE_SY2) + printf("background region of interest: (%3d,%3d) (%3d,%3d)\n",\\ + IMAGE_BX1,IMAGE_BY1,IMAGE_BX2,IMAGE_BY2) + printf("image dimensions (x*y) : %3d * %3d pixels\n",\\ + IMAGE_XDIM,IMAGE_YDIM) + +}' + +#+ +#------------------------------------------------------------------------------ +# imageGetInt - This macro analyzes the last image taken by the active area +# detector. It checks the region-of-interest defined via +# imageSetRoi and sets some global variables to the intensity +# values determined. Calling parameters are the three threshold +# values (no. of pixels with intensity above these values is +# returned). +#- + +def imagegetint 'imageGetInt' + +def imageGetInt '{ +# =========== + + global IMAGE_DEVICE, IMAGE_IS_ON + global IMAGE_FILENAME, IMAGE_PATH, IMAGE_FNUM, IMAGE_FBASE + global IMAGE_INFO_FILENAME, IMAGE_HEADER_LENGTH + global IMAGE_XDIM, IMAGE_YDIM, IMAGE_COLOR_DEPTH + global IMAGE_I_SIG, IMAGE_I_BG, IMAGE_I_SUM + global IMAGE_AREA_SIG, IMAGE_AREA_BG + global IMAGE_THRESH1, IMAGE_THRESH2, IMAGE_THRESH3, IMAGE_THRESH4 + global IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT + global IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT + global IMAGE_SX1, IMAGE_SY1, IMAGE_SX2, IMAGE_SY2 + global IMAGE_BX1, IMAGE_BY1, IMAGE_BX2, IMAGE_BY2 + + local unixCommand, unixReturn + + if ($# != 4) { + eprint "Wrong number of arguments in \'imageGetInt\'" + eprint "Usage:" + eprint "imageGetInt " + exit + } + + commandDir = "" + unix(sprintf("dirname %s", IMAGE_MAC),commandDir) + if(index(commandDir,"\n") != 0){ + commandDir = substr(commandDir,0,length(commandDir)-1) + } + + unixCommand = sprintf("%s%s %s %d %d %d %d -median 30",\\ + commandDir,\\ + "/bin/image_get_int.py",\\ + "/tmp/spec_image_info.dat",\\ + $1, $2, $3, $4) + + if(IMAGE_DEBUG){ + printf("unix command: %s\n", unixCommand) + } + + unixReturn = "" + unix(unixCommand,unixReturn) + + if(IMAGE_DEBUG){ + printf("unix return: %s\n", unixReturn) + } + + IMAGE_I_SUM = "" + IMAGE_AREA_SIG = "" + IMAGE_THRESH1_COUNT = "" + IMAGE_THRESH2_COUNT = "" + IMAGE_THRESH3_COUNT = "" + IMAGE_I_BG = "" + IMAGE_AREA_BG = "" + + if (sscanf(unixReturn,"I_sum %d area_I %d Threshold1 %d Threshold2 %d Threshold3 %d Threshold4 %d I_bgr %d area_bgr %d",\\ + IMAGE_I_SUM, IMAGE_AREA_SIG,\\ + IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT, IMAGE_THRESH3_COUNT,\\ + IMAGE_THRESH4_COUNT, IMAGE_I_BG, IMAGE_AREA_BG) != 8) { + printf("Couldn\'t get intensity data\n") + exit + } + if (IMAGE_AREA_BG > 0){ + IMAGE_I_SIG = IMAGE_I_SUM - ((IMAGE_I_BG / IMAGE_AREA_BG) * IMAGE_AREA_SIG) + } else { + IMAGE_I_SIG = IMAGE_I_SUM + } + + if (IMAGE_DEBUG){ + printf("I_sum: %d, area_I: %d\nthresh1: %d, thresh2: %d, thresh3: %d, thresh4: %d\n",\\ + IMAGE_I_SUM, IMAGE_AREA_SIG,\\ + IMAGE_THRESH1_COUNT, IMAGE_THRESH2_COUNT,\\ + IMAGE_THRESH3_COUNT, IMAGE_THRESH4_COUNT) + printf("I_bgr: %d, area_bgr: %d\n",IMAGE_I_BG,IMAGE_AREA_BG) + } + +}' + +#+ +#------------------------------------------------------------------------------ +#- +#============================================================================== +# +##################################################### +# 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: image.mac,v $ +# Revision 1.11 2008/03/20 13:36:14 schlepuetz +# removed quotation marks around argument variables ,,... in imageSetRoi, added imageShowRoi. +# +# Revision 1.10 2007/04/22 15:42:11 schlepuetz +# changed imageCheckROI to allow for ROIs of 1 pixel width/height. +# +# Revision 1.9 2007/04/05 09:57:21 schlepuetz +# new error message if image file to be analyzed is not found +# +# Revision 1.8 2006/12/01 08:28:52 schlepuetz +# include wait loop in imageUserGetcounts to make sure the image file is available and non-empty +# +# Revision 1.7 2006/09/21 11:49:43 schlepuetz +# added new feature in imageGetInt to selectively median filter hot and dead pixels +# +# Revision 1.6 2006/08/09 13:44:38 schlepuetz +# added more input options for imageSetRoi. +# +# Revision 1.5 2006/06/23 16:26:52 schlepuetz +# missing bracket... +# +# Revision 1.4 2006/06/23 08:07:32 schlepuetz +# copy image info file also into image directory for accessibility +# +# Revision 1.3 2006/03/01 13:02:47 maden +# Check-in newer version from /work ... +# +# Revision 1.2 2005/12/10 16:32:57 schlepuetz +# fixed bug in imageGetInt. +# +# Revision 1.1 2005/11/10 11:01:21 schlepuetz +# first tested version of this file +# +# +#============================= End of $RCSfile: image.mac,v $ === \ No newline at end of file diff --git a/script/spec/pixel.py b/script/spec/pixel.py new file mode 100644 index 0000000..e47113a --- /dev/null +++ b/script/spec/pixel.py @@ -0,0 +1,1525 @@ +#============================================================================== +# Macroname: pixel.mac +# ========= +#+ +# $Date: 2009/05/28 10:10:56 $ +# $Author: schlepuetz $ +# $Source: /cvs/G/SPEC/local/X04SA/ES3/pixel.mac,v $ +# $Revision: 1.11 $ +# $Tag: $ +# +# Description: Macro definitions to control a PILATUS pixel detector from +# SPEC. +# +# Note: This macro is based on the original ccd.mac, Rev. 1.16, by +# D. Maden and has been adapted to serve the pixel detector +# exclusively. +# +# Authors(s): D. Maden (DM), 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 Institute +# CH - 5232 Villigen PSI +# Created: 2005/07/13 +# +#- +# Chained macro definitions affected by this macro: +# ------------------------------------------------- +# - user_precount +# - user_waitcount +# - user_ct +# - user_pre_recount +# - user_prescan_head +# +# Change Log: +# ----------- +# +# 13.07.2005 (CS): +# - modified D. Maden's ccd.mac, removed all code related to the Hystar +# CCD camera, added pixon, pixoff & pixconnected(). +# - All EPICS channels used in this macro are still the same as in ccd.mac +# This will have to be changed for the new EPICS interface of the +# PILATUS II pixel detector. +# +# 2005/11/07 (CS): +# - reduced sleep time in pixwait to 0.05 seconds. +# +# 2005/11/30 (CS): +# - fixed timing problem with pixlogwrite (now executed in user_count_end) +# - resolved issues with pixwait running into timeouts for long exposures. +# +# 2006/06/14 (CS): +# - fixed bug in pixUserCountEnd: COUNT_ID was set to value in EPICS channel +# PIX_FNUM_CHN, which is incremented immediately after an exposure such that +# COUNT_ID always reflected the image number of the next image to be taken. +# Now this value is decremented by 1 to give the number of the image taken +# last. +# +# 2006/12/13 (CS): +# - removed requirement that exposuretime must be an integer multiple of 0.001 +# seconds in 'pixsetexpose'. This has become obsolete with PilatusII. +# +# 2009/05/28 (CS): +# - removed PilatusI support. +# Macro now only works with Pilatus 100k single modules. +# - added macro 'pixgetfilefmt' to check for the requested image file type +# (img,edf,tif), and set PIX_FILE_HEADER_LENGTH accordingly (0,1024,4096). +# - added call to 'pixgetfilefmt' in 'pixUserPrecount' and 'pixsetfmt' +#------------------------------------------------------------------------------ +# Version for X04SA ISSD (ES3) at SLS +# + global PIXEL_MAC +# + PIXEL_MAC = DOFILE # Save the name of this macro file. + # (Used for the help function). +# +#+ +#============================================================================== +# This macro file contains the following commands: +#- +# +#+ +#------------------------------------------------------------------------------ +# pixhelp - generate help text. This is obtained by displaying +# the file pix.txt, which should sit in the same +# directory as this file. +#- + +# allow for misspelled help commands: +def helpPIX 'pixhelp' +def helpPix 'pixhelp' +def helppix 'pixhelp' +def pixHelp 'pixhelp' + +def pixhelp '{ +# ======= + + local file, ll + + unix (sprintf ("dirname %s", PIXEL_MAC), _1) + ll = length (_1) + if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1)) + file = sprintf ("%s/pixel.txt", _1) + if (file_info (file, "-e")) { + unix (sprintf ("cat %s | less", file)) + } else { + printf ("\n Macros available in file pix.mac ($$Revision: 1.11 $$):\n") + print " =======" + print "" + print " pixon - " + print " pixoff - " + print " pixconnected() - " + print " pixsetup - interactively configure the pixel" + print " detector package." + print " pixsetpath - interactively set directory for file storage." + print " pixsetfmt - interactively set file name template." + print " pixsetexpose - set exposure time." + print " pixshow - show the PIX settings." + print " pixsnap [] - take an image and write it to disk." + print " pixresnap - take an image and overwrite file." + print " pixwait - wait for the PIX sub-system to become \"Ready\"." + print " pixsw [] - call pixsnap and then pixwait." + print " pixlogon [] - turn on the pix log." + print " pixlogoff - turn off the pix log." + print " pixlogshow - show info about the pix log." + print " pixlogwrite - write a pix log file." + } + }' + +#+ +#------------------------------------------------------------------------------ +# pixon - turns on counting using the pixel detector instead +# of the point detector. +#- + +def pixon '{ +# ===== + + global BEAMLINE, ENDSTATION + + global IMAGE_DEVICE, IMAGE_IS_ON + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + + #-------------------------------- + # set the global status variables + # and report status to the user + + if(IMAGE_DEVICE!=""){ + if(IMAGE_DEVICE=="PILATUS"){ + if(PIX_IS_ON==1){ + printf("The PILATUS pixel detector was and still is enabled.\n") + } else{ + printf("The PILATUS pixel detector has been enabled.\n") + PIX_IS_ON = 1 + } + } else{ + printf("The following image device is currently connected: %s\n",\\ + IMAGE_DEVICE) + printf("Please disable this device before calling \'pixon\' again.\n") + exit + } + } else{ + if(PIX_IS_ON==1){ + IMAGE_DEVICE="PILATUS" + printf("The PILATUS pixel detector has been enabled.\n") + } else{ + IMAGE_DEVICE="PILATUS" + PIX_IS_ON = 1 + printf("The PILATUS pixel detector has been enabled.\n") + } + } + + #---------------------------------------- + # deactivate the Cyberstar point detector + + cyberOff + + #------------------------------------------- + # run the setup macro for the pixel detector + # if it has not been executed + + if (PIX_STATUS_CHN == 0){ + pixsetup + } + + #------------------------------------------- + # define necessary chained macro definitions + # and add them to their respective + # destination macros. + + #------------------ + def pixUserPrecount \' + # =============== + + global PIX_IS_ON + + if ((PIX_IS_ON) && (pixconnected())) { + pixsetexpose COUNT_TIME + pixgetfilefmt + pixsnap + } + \' + # add pixUserPrecount to the end of user_precount + cdef("user_precount","pixUserPrecount; ","pix_user_precount_key",0x20) + + #------------------- + def pixUserWaitcount \' + # ================ + + global PIX_IS_ON + + if (PIX_IS_ON) { + pixwait + } + \' + # add to user_waitcount + cdef("user_waitcount","pixUserWaitcount; ","pix_user_waitcount_key") + + + #------------ + def pixUserCt \' + # ========= + + global PIX_IS_ON + + if ((PIX_IS_ON) && (pixconnected())) { + printf("image written to: /sls/X04SA/data/x04sa/ES3/pixel/images/%s%s%s\n",\\ + epics_get(PIX_PATHA_CHN),\\ + epics_get(PIX_PATHB_CHN),\\ + epics_get(PIX_FNAM_CHN)) + } + \' + # add to user_ct + cdef("user_ct","pixUserCt; ","pix_user_ct_key",0x20) + + #------------------ + def pixUserCountEnd \' + # =============== + + global PIX_IS_ON, PIX_LOG, IMAGE_FILENAME, COUNT_ID + + # update the IMAGE_FILENAME and COUNT_ID variables + if ((PIX_IS_ON) && (pixconnected())) { + IMAGE_FILENAME = sprintf("/sls/X04SA/data/x04sa/ES3/pixel/images/%s%s%s",\\ + epics_get(PIX_PATHA_CHN),\\ + epics_get(PIX_PATHB_CHN),\\ + epics_get(PIX_FNAM_CHN)) + COUNT_ID = epics_get(PIX_FNUM_CHN)-1 + } + + # write the image log if logging is enabled + if (PIX_IS_ON && (PIX_LOG != "")){ + pixlogwrite + } + \' + # add to user_count_end + cdef("user_count_end","pixUserCountEnd; ","pix_user_count_end_key") + + #-------------------- + def pixUserPreRecount \' + # ================= + + pixUndo + + \' + # add pixUserPreRecount to user_pre_recount + cdef("user_pre_recount","pixUserPreRecount; ","pix_user_pre_recount_key") + + #----------------- + def pixPrescanHead \' + # ============== + + if (PIX_IS_ON) { + printf("\nfirst image will be: /sls/X04SA/data/x04sa/ES3/pixel/images/%s%s%s\n\n",\\ + epics_get(PIX_PATHA_CHN),\\ + epics_get(PIX_PATHB_CHN),\\ + sprintf(epics_get("X04SA-ES3-CCD:FNAM_FMT"),\\ + epics_get("X04SA-ES3-CCD:FNUM")+1)) + } + \' + # add to user_prescan_head + cdef("user_prescan_head","pixPrescanHead; ","pix_prescan_head_key",0x20) + + #----------------------------------- + # Enable the image analysis routines + + imageInit # make sure all global variables are defined + IMAGE_THRESH1 = PIX_THRESH1 + IMAGE_THRESH2 = PIX_THRESH2 + IMAGE_THRESH3 = PIX_THRESH3 + IMAGE_THRESH4 = PIX_THRESH4 + IMAGE_HEADER_LENGTH = PIX_FILE_HEADER_LENGTH + IMAGE_COLOR_DEPTH = PIX_COLOR_DEPTH + IMAGE_XDIM = PIX_XDIM + IMAGE_YDIM = PIX_YDIM + imageOn # turn on image analysis support + +}' + +#+ +# ----------------------------------------------------------------------------- +# pixoff - turns off the pixel detector as counting device and +# enables the point detector again. +#- + +def pixoff '{ +# ====== + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + # remove from user_precount + cdef("user_precount","","pix_user_precount_key","delete") + + # remove from user_waitcount + cdef("user_waitcount","","pix_user_waitcount_key","delete") + + # remove from user_prescan_head + cdef("user_prescan_head","","pix_prescan_head_key","delete") + + # remove pixUserCountEnd from user_count_end + cdef("user_count_end","","pix_user_count_end_key","delete") + + # remove from user_ct + cdef("user_ct","","pix_user_ct_key","delete") + + # remove pixUserPreRecount from user_pre_recount + cdef("user_pre_recount","","pix_user_pre_recount_key",\\ + "delete") + + #----------------------- + # turn off imaging tools + imageOff + + #----------------------- + # activate cyberstar point detector + cyberOn + + #-------------------------------- + # set the global status variables + # and report status to the user + + if (PIX_IS_ON != 0) { + PIX_IS_ON = 0 + printf("The pixel detector has been disbled.\n") + } else { + printf("The pixel detector was and still is disabled.\n") + } + +}' + +#+ +# ----------------------------------------------------------------------------- +# pixconnected() - checks whether pixel detector is properly connected +# with SPEC via EPICS. +# Returns 1 if the pixel is connected, 0 otherwise. +#- + +def pixconnected() '{ +# ============== + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local isConnected + + isConnected = 1 + if (epics_get("X04SA-ES3-CCD:STAT1") != "Connected") { + eprint "The Pixel detector is not connected to Epics/Spec." + eprint "Please disconnect in tvx and connect via the CCD/Pixel Epics widget." + isConnected = 0 + } else { + if (epics_get("X04SA-ES3-CCD:ERRCODE") != 0) { + eprint "The pixel detector returned an error. It may not be properly" + eprint "connected. Please disconnect in tvx and disconnect and" + eprint "re-connect with the CCD/Pixel Epics widget." + isConnected = 0 + } + } + return (isConnected) +}' + +#+ +#------------------------------------------------------------------------------ +# pixsetup - setup the pixel detector. +# +# Usage : pixsetup [] +# then answer the questions. +# The optional specifies the directory where +# the pixel detector images will be stored. If +# is not supplied, the user will be prompted for a path. +#- + +def pixsetup '{ +# ======== + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON, PIX_TYPE + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local idx, my_type, my_file_path, my_file_fmt, my_path, my_pathA, my_pathB + local my_fnum, my_exp, my_gain + + PIX_PATHA_CHN = sprintf ("%s-%s-CCD:PATHa", BEAMLINE, ENDSTATION) + PIX_PATHB_CHN = sprintf ("%s-%s-CCD:PATHb", BEAMLINE, ENDSTATION) + PIX_FNAM_FMT_CHN = sprintf ("%s-%s-CCD:FNAM_FMT", BEAMLINE, ENDSTATION) + PIX_FNUM_CHN = sprintf ("%s-%s-CCD:FNUM", BEAMLINE, ENDSTATION) + PIX_FNAM_CHN = sprintf ("%s-%s-CCD:FNAM", BEAMLINE, ENDSTATION) + PIX_EXPOSE_CHN = sprintf ("%s-%s-CCD:EXPOSE", BEAMLINE, ENDSTATION) + PIX_STATUS_CHN = sprintf ("%s-%s-CCD:STATUS", BEAMLINE, ENDSTATION) + PIX_TRIG_CHN = sprintf ("%s-%s-CCD:TRIG", BEAMLINE, ENDSTATION) + + if(!(($#==1) || ($#==0))){ + eprint "Wrong number or illegal arguments in \'pixsetup\'" + eprint "Usage:" + eprint " pixsetup []" + eprint "" + eprint "The argument specifies the directory where the pixel" + eprint "detector images are stored and is optional. If none is supplied," + eprint "the user will be prompted for the path." + exit + } + + #------------------------------------------------------------------- + # set the four threshold values for the acceptable, good, optimum, + # and maximum number of counts according to the pixel detector model. + # If Used in combination with automatic filter and exposure time settings, + # (auto-level > 0, see auto.mac), these threshold values are used to deter- + # mine the action taken after a count command. + # The four threshold levels are used in the following way (MaxCount + # represents the highest count value within the defined region of interest, + # see image.mac): + # 0 <= MaxCount < Thresh1 : counts are very low -> increase intensity + # if possible by increasing the filter + # transmission or the exposure time, give up + # otherwise. + # Thresh1 <= MaxCount < Thresh2 : counts are acceptable -> increase filter + # transmission if possible but keep current + # exposure time, accept otherwise. + # Thresh2 <= MaxCount < Thresh3 : counts are good -> try to decrease exposure + # time first, then increase filter + # transmission if possible, accept otherwise. + # Thresh3 <= MaxCount < Thresh4 : optimal counts -> no action taken. + # Thresh4 <= MaxCount : counts are too high -> intensity is reduced + + # set global variables for the Pilatus 100k single module device + PIX_TYPE = "PilatusII" + PIX_FILE_HEADER_LENGTH = 0 + PIX_COLOR_DEPTH = 32 + PIX_XDIM = 487 + PIX_YDIM = 195 + PIX_THRESH1 = 40 + PIX_THRESH2 = 500 + PIX_THRESH3 = 8000 + PIX_THRESH4 = 100000 + + + #---------------------------------------------- + # set up the pixel detector file and path names + + if($#==1){ + pixsetpath $1 + } else{ + pixsetpath + } + + pixsetfmt + # Get the user to check the frame number. + # + my_fnum = epics_get (PIX_FNUM_CHN) + my_fnum = getval ("Next frame number", (my_fnum + 1)) + my_fnum = (my_fnum >= 1) ? (my_fnum - 1) : 0 + # Get the user to check the exposure time. + # + my_exp = (epics_get(PIX_EXPOSE_CHN))/1000 + epics_put (PIX_FNUM_CHN, my_fnum) + + #--------------------------------- + # define the initial exposure time + + my_exp = getval ("Exposure time in sec", my_exp) + my_exp = (my_exp < 0.000005) ? 0.000005 : my_exp + epics_put (PIX_EXPOSE_CHN, my_exp*1000) + + PIX_EXP_START_TIME = time() - 100000 # initialize PIX_EXP_START_TIME (to a + # long time ago!) + + pixshow # display pixel detector information +}' + +#+ +#------------------------------------------------------------------------------ +# pixsetpath - specify the path for pixel detector image files. +# +# Usage : pixsetpath [] +# if the optional is not specified the user is +# prompted for the path. +#- + +def pixsetpath '{ +# ========== + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local my_file_path, my_pathA, my_pathB, ll, i + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } + if($# == 1){ + my_file_path = "$1" + _1 = my_file_path + _2 = "" + } else if ($# == 0){ + # Get the bits of the file name + # from the EPICS channels + _1 = epics_get (PIX_PATHA_CHN) + _2 = epics_get (PIX_PATHB_CHN) + my_file_path = sprintf ("%s%s", _1, _2) + } else{ + eprint "\n\aWrong number or illegal arguments in \'pixsetpath\'\n" + eprint "Usage:" + eprint " pixsetpath []" + eprint "" + eprint "The argument is optional, if none is supplied the user" + eprint "will be prompted for the path." + exit + } + + if (index (my_file_path, "\\") != 0) { + # There is a backslash in the path, so it is probably + # a windows filename. Switch to default linux path. + my_file_path = "/home/pixel/sls8x2/images/" + epics_put (PIX_FNAM_FMT_CHN, "px%05d.img") + } else { + ll = length (_1) + if ((ll > 0) && (substr (_1, ll, 1) != "/")) { + _1 = sprintf ("%s%s", _1, "/") + } + _1 = sprintf ("%s%s", _1, _2) + ll = length (_1) + if ((ll > 0) && (substr (_1, ll, 1) != "/")) { + _1 = sprintf ("%s%s", _1, "/") + } + my_file_path = _1 + } + + printf ("Image file directory is: \"%s\"\n", my_file_path) + while (!yesno ("Is this OK", 1)) { + _1 = input ("Specify directory> ") + if (length (_1) > 70) { + print "\aToo long." + continue + } + ll = length (_1) + if ((ll > 0) && (substr (_1, ll, 1) != "/")) { + _1 = sprintf ("%s%s", _1, "/") + } + + my_file_path = _1 + printf ("Image file directory is: \"%s\"\n", my_file_path) + } + if (length (my_file_path) > 37) { + # The string must be split. Split it + # at a "/" or "\" + splitChar = "/" + i = length (my_file_path) + while (i >= 0) { + if ((substr (my_file_path, i, 1) == splitChar) && \ + (i <= 37)) { + break + } + i-- + } + my_pathA = substr (my_file_path, 1, i) + my_pathB = substr (my_file_path, (i + 1)) + if ((length (my_pathA) > 37) || \ + (length (my_pathB) > 37)) { + print "Sorry, path is too long and cannot be legally split." + unglobal PIX_IS_ON + exit + } + } else { + my_pathA = my_file_path + my_pathB = "" + } + + epics_put (PIX_PATHA_CHN, my_pathA) + epics_put (PIX_PATHB_CHN, my_pathB) + }' + +#+ +#------------------------------------------------------------------------------ +# pixsetfmt - specify the name template for image files. +# +# Usage : pixsetfmt +# then answer the questions. +#- + +def pixsetfmt '{ +# ========= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local ll, my_fmt + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } + # Get the current file name template + # + _1 = epics_get (PIX_FNAM_FMT_CHN) + ll = length (_1) + if (ll == 0) { + _1 = "px%05d.img" + ll = length (_1) + } + my_fmt = _1 + if (pixCheckFileFmt (my_fmt, 0) != 0) { + my_fmt = "px%05d.img" + } + + printf ("File name template is: \"%s\"\n", my_fmt) + while (!yesno ("Is this OK", 1)) { + my_fmt = input ("Specify file name template> ") + if (length (my_fmt) > 30) { + print "\aToo long." + continue + } + if (pixCheckFileFmt (my_fmt, 1) != 0) { + my_fmt = "px%05d.img" + print "Template has been set to", my_fmt + } + printf ("File name template is: \"%s\"\n", my_fmt) + } + + epics_put (PIX_FNAM_FMT_CHN, my_fmt) + + # retrieve the image file format from the name template + pixgetfilefmt + +}' + + +#+ +#------------------------------------------------------------------------------ +# pixsetexpose - specify the exposure time in secons [s]. +# +# Usage : pixsetexpose +#- + +def pixsetexpose '{ +# ============ + + global BEAMLINE, ENDSTATION + + global COUNT_TIME + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local ll, my_fmt + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } + if ($# != 1) { + printf ("\aUsage: pixsetexpose \n") + exit + } + + if ($1 <= 0) { + printf ("\aExposure time must be greater than zero! Aborting...\n") + exit + } + + # convert to ms for the EPICS Pixel widget. + _1 = $1*1000 + + epics_put (PIX_EXPOSE_CHN, _1) + COUNT_TIME = $1 + +}' + +#+ +#------------------------------------------------------------------------------ +# pixshow - show the current pixel detector settings +# +# Usage : pixshow +#- + +def pixShow 'pixshow' + +def pixshow '{ +# ======= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local fnam, pathA, pathB, idx, i + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } + + if(PIX_IS_ON==1){ + printf("\nThe PILATUS pixel detector is currently enabled.\n") + printf("To disable it type \'pixoff\'.\n") + } else{ + printf("\nThe PILATUS pixel detector is currently disabled.\n") + printf("To enable it type\'pixon\'.\n") + } + + pathA = epics_get (PIX_PATHA_CHN) + pathB = epics_get (PIX_PATHB_CHN) + PIX_PATH = sprintf ("%s%s", pathA, pathB) + + PIX_FILE_FMT = epics_get (PIX_FNAM_FMT_CHN) + + printf("\nThe current pixel detector settings are:\n") + + if (index (PIX_FILE_FMT, "%") != 0) { + PIX_FNUM = epics_get (PIX_FNUM_CHN) + printf (" The frame number = %d\n", PIX_FNUM) + printf (" The file path is: %s\n", PIX_PATH) + printf (" The file template is: %s\n", PIX_FILE_FMT) + fnam = epics_get (PIX_FNAM_CHN) + printf (" The last file name was: %s\n", fnam) + fnam = sprintf (PIX_FILE_FMT, (PIX_FNUM + 1)) + printf (" The next file name will be: %s\n", fnam) + } else{ + fnam = epics_get (PIX_FNAM_CHN) + printf (" The last file name was: %s\n", fnam) + printf (" The next file name will be: %s\n", PIX_FILE_FMT) + } + pixCheckFileFmt (PIX_FILE_FMT, 1) + + PIX_EXPOSE = epics_get (PIX_EXPOSE_CHN) + printf(" Exposure time = %5d sec\n", PIX_EXPOSE/1000) + + printf(" Image dimensions: %d x %d pixels (total = %d)\n", \\ + PIX_XDIM, PIX_YDIM, PIX_XDIM*PIX_YDIM) + printf(" Threshold values: Thresh1 = %d, Thresh2 = %d, Thresh3 = %d, Thresh4 = %d\n",\\ + PIX_THRESH1,PIX_THRESH2,PIX_THRESH3,PIX_THRESH4) + + if(PIX_IS_ON==1){ + if(IMAGE_DEVICE==""){ + printf("No imaging device is active.\n") + printf("Type \'pixon\' to make the PILATUS pixel detector the active ") + printf("imaging device.\n") + } else if(IMAGE_DEVICE!="PILATUS"){ + printf("\nThe current imaging device is %s\n", IMAGE_DEVICE) + printf("To make the PILATUS pixel detector the active imaging device, ") + printf("disable the %s",IMAGE_DEVICE) + printf("imaging device and type \'pixon\'.\n") + } + } + + if(IMAGE_IS_ON==1){ + imageShow + } else{ + printf("\nImage analysis support is currently disabled.\n") + printf("To enable it type \'imageOn\'.\n") + } + +}' + +#+ +#------------------------------------------------------------------------------ +# pixsnap - get the PIX to take an image and write it to disk. +# +# Usage : pixsnap [] +# +# If a filename is specified, this will be used to specify the +# file which is to be written. Otherwise, the frame number will +# be incremented and a filename will be generated from the +# file-name template. +# +# If is specified, it is assumed to be relative to +# the file-name path which has been defined via pixsetpath. +#- + +def pixsnap '{ +# ======= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local stat + + if (($# != 0) && ($# != 1)) { + print "\n\a Usage:" + print " pixsnap []" + exit + } + + if ((whatis ("PIX_IS_ON") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } else if (!PIX_IS_ON){ + printf ("\aThe pixel detector is currently not enabled. Use the \"pixon\"") + printf ("command to enable it. Aborting...") + exit + } else{ + + pixwait # Wait until pixel detector is ready + + if ($# == 0) { + PIX_EXPOSE = epics_get(PIX_EXPOSE_CHN) + epics_put (PIX_TRIG_CHN, "Inc+Sn+Wr") + PIX_EXP_START_TIME = time() + } else { + PIX_EXPOSE = epics_get(PIX_EXPOSE_CHN) + epics_put (PIX_FNAM_CHN, "$1") + epics_put (PIX_TRIG_CHN, "Snap") + PIX_EXP_START_TIME = time() + pixwait + epics_put (PIX_TRIG_CHN, "Write") + cmnd = sprintf ("pixlogwrite %s.pxl", fnam) + eval (cmnd) + } + } +}' + +#+ +#------------------------------------------------------------------------------ +# pixUndo - decrement the pixel detector image number by 1 to repeat +# the exposure and overwrite the last file. +# +# Usage : pixUndo +#- + +def pixUndo '{ +# ======= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local imageFileNumber + + if ($# != 0) { + printf ("\aThere should be no arguments.\n") + exit + } + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } else if (!PIX_IS_ON){ + printf ("\aThe pixel detector is currently not enabled. Use the \"pixon\"") + printf ("command to enable it. Aborting...") + exit + } else{ + # get the file number of the next file and decrease it by 1 + imageFileNumber = epics_get(PIX_FNUM_CHN) + imageFileNumber = imageFileNumber-1 + epics_put(PIX_FNUM_CHN,imageFileNumber) + printf("File number decreased.\n") + } +}' + +#+ +#------------------------------------------------------------------------------ +# pixresnap - get the pixel detector to take an image and overwrite the +# previous disk file. +# +# Usage : pixresnap +#- + +def pixresnap '{ +# ========= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local fnam, cmnd + + if ($# != 0) { + printf ("\aThere should be no arguments.\n") + exit + } + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } else if (!PIX_IS_ON){ + printf ("\aThe pixel detector is currently not enabled. Use the \"pixon\"") + printf ("command to enable it. Aborting...") + exit + } else{ + # Get the name of the last file + fnam = epics_get (PIX_FNAM_CHN) + # Compose a command to use it. Maybe there is a + # better way of doing this, but I do not know how! + cmnd = sprintf ("pixsnap %s", fnam) + # And execute it. + eval (cmnd) + } +}' + +#+ +#------------------------------------------------------------------------------ +# pixwait - wait for the pixel detector sub-system to become "Ready". +#- + +def pixwait '{ +# ======= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local cnt, trig, stat, smsFlag + + if ((whatis ("PIX_TYPE") & 0x08000000) != 0) { + printf ("\n\aThe pixel detector software has not been initialised!\n") + printf ( "Use the \"pixsetup\" command.\n") + exit + } else if (!PIX_IS_ON){ + printf ("\aThe pixel detector is currently not enabled. Use the \"pixon\"") + printf ("command to enable it. Aborting...") + exit + } + + cnt = 0 + # + # First wait for "TRIG" to go back to idle. This should + # ensure that execution of the command has started. + # + trig = epics_get (PIX_TRIG_CHN, "long") + while (trig != 0) { + cnt = cnt + 1 + if (cnt > 1000) { + printf("Triger signal still busy, pixwait timed-out!\n") + exit + } + sleep (0.05) + trig = epics_get (PIX_TRIG_CHN, "long") + } + + # + # Then wait for exposure time to elapse. + # (PIX_EXPOSE is in milliseconds!) + # + while (time() <= PIX_EXP_START_TIME+(PIX_EXPOSE/1000)){ + sleep(0.05) + } + + # + # Then wait for the pixel detector to become ready. + # Wait time is 1000 x 0.05 sec = 50 sec. + # + smsFlag = 0 + stat = epics_get (PIX_STATUS_CHN, "string") + while ((stat != "Ready0") && (stat != "Ready1")) { + cnt = cnt + 1 + if (cnt > 1000) { + printf("%s %s", "pixwait: Pixel status did not return to \"Ready\" within 50", \\ + "seconds.\n") + beep; beep; beep; beep; beep; + if (smsFlag == 0) { + smsSendMessage ("Pixel detector problem in pixwait.") + } + smsFlag = 1 + printf ("\n") + secs=15 + while (secs > 0) { + printf ("\r\aHit any keyboard character within %3d secs to abort.", secs) + sleep (1.0) + _9 = input (-1) + if (length (_9) > 0) { + beep; printf ("\nAborted.\n") + exit + } + secs-- + } + printf ("Trying for another 50 secs\n") + } + if ((stat == "Undefined") || \ + (stat == "Time-out") || \ + (stat == "Error")) { + print "\aInvalid PIX status:", stat + exit + } + sleep (0.05) + stat = epics_get (PIX_STATUS_CHN, "string") + } + if (smsFlag == 1) { + smsSendMessage ("Pixel detector seems to have recovered from error.") + } +}' + +#+ +#------------------------------------------------------------------------------ +# pixsw - call pixsnap and then pixwait. +# +# Usage : pixsw [] +# +# See pixsnap and pixwait for a description. +#- + +def pixsw '{ +# ===== + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + pixsnap $* + pixwait +}' + +#+ +#------------------------------------------------------------------------------ +# pixlogon - turn on logging of EPICS stuff on each snap +# +# Usage : pixlogon [] +# +# Turn on logging. If an argument is supplied, it specifies a directory +# for holding the log files. If it is not specified, the user will +# be prompted. +#- + +def pixlogon '{ +# ======== + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local myPathA, myPathB, myPath, myDir, myFile + + PIX_LOG = "" # Disable logging in case of errors. + + if (($# != 0) && ($# != 1)) { + print "Usage: pixlogon []" + exit + } + if ($# != 1) { + myPathA = epics_get (PIX_PATHA_CHN) + myPathB = epics_get (PIX_PATHB_CHN) + myPath = sprintf ("%s%s", myPathA, myPathB) + myDir = getsval ("Specify a directory", myPath) + } else { + myDir = "$1" + } + if (substr (myDir, length (myDir)) != "/") { + myDir = sprintf ("%s/", myDir) + } + if (!file_info (myDir, "-e")) { + printf ("\aSorry, %s does not exist.\n", myDir) + exit + } + if (!file_info (myDir, "isdir")) { + printf ("\aSorry, %s is not a directory.\n", myDir) + exit + } + myFile = sprintf ("%s/%s", myDir, "spec.test") + if (file_info (myFile, "-e")) { + unix (sprintf ("rm %s", myFile)) + if (file_info (myFile, "-e")) { + printf ("\aCannot delete a test file in this directory.\n") + exit + } + } + fprintf (myFile, "This is a test record\n") + close (myFile) + if (!file_info (myFile, "-e")) { + printf ("\aSorry, %s is not a writable directory.\n") + exit + } + unix (sprintf ("rm %s", myFile)) + + unix (sprintf ("dirname %s", PIXEL_MAC), _1) + ll = length (_1) + if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1)) + myFile = sprintf ("%s/ccd-log.req", _1) + ###PIX_LOG_CMND = sprintf ("casave -asciiin %s -asciiout %%s", myFile) + PIX_LOG_CMND = sprintf ("X_X04SA_do_casave.py -- -asciiin %s -asciiout %%s", myFile) + + PIX_LOG = myDir + printf ("logging of image-related info to %s has been turned on.\n", myDir) + +}' + +#+ +#------------------------------------------------------------------------------ +# pixlogoff - turn off logging on each pixel detector snap +# +# Usage : pixlogoff +#- + +def pixlogoff '{ +# ========= + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + PIX_LOG = "" # Disable logging. + printf ("logging of image-related info has been turned off.\n") +}' + +#+ +#------------------------------------------------------------------------------ +# pixlogshow - display the snap logging status. +# +# Usage : pixlogshow +#- + +def pixlogshow '{ +# ========== + + global BEAMLINE, ENDSTATION + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + if (PIX_LOG == "") { + printf ("\nPIX snap logging is off.\n") + } else { + printf ("\nPIX snap logging is on. The log directory is:\n") + printf ("\n %s\n", PIX_LOG) + printf ("\nThe log command is:\n") + printf ("\n %s\n", PIX_LOG_CMND) + } +}' + +#+ +#------------------------------------------------------------------------------ +# pixlogwrite - write a pixel detector snap log file. +# +# Usage : pixlogwrite [] +# +# Write a PIX snap log file. The file name is either derived from the +# name of the snap file or is the specified argument. +#- + +def pixlogwrite '{ +# =========== + + global BEAMLINE, ENDSTATION + + global PIX_IS_ON + + global PIX_PATHA_CHN, PIX_PATHB_CHN + global PIX_FNAM_FMT_CHN, PIX_FNUM_CHN, PIX_FNAM_CHN + global PIX_EXPOSE_CHN + global PIX_STATUS_CHN, PIX_TRIG_CHN + + global PIX_PATH, PIX_FILE_FMT, PIX_FNUM, PIX_EXPOSE, PIX_EXP_START_TIME + global PIX_LOG, PIX_LOG_CMND + global PIX_COLOR_DEPTH, PIX_FILE_HEADER_LENGTH + global PIX_THRESH1, PIX_THRESH2, PIX_THRESH3, PIX_THRESH4 + global PIX_XDIM, PIX_YDIM + + local myFile, myCmnd + + if (PIX_LOG != "") { + # Put our local variables into EPICS to allow fast writing + epics_put ("X04SA-ES3-MOT:phi", A[motor_num(phi)]) + epics_put ("X04SA-ES3-MOT:omegaH", A[motor_num(oh)]) + epics_put ("X04SA-ES3-MOT:nu", A[motor_num(nu)]) + epics_put ("X04SA-ES3-MOT:omegaV", A[motor_num(ov)]) + epics_put ("X04SA-ES3-MOT:alpha", A[motor_num(alp)]) + epics_put ("X04SA-ES3-MOT:delta", A[motor_num(del)]) + epics_put ("X04SA-ES3-MOT:gamma", A[motor_num(gam)]) + #epics_put ("X04SA-ES3-MOT:2-thetaA", A[motor_num(ttha)]) + #epics_put ("X04SA-ES3-MOT:omegaA", A[motor_num(oa)]) + epics_put ("X04SA-ES3-MOT:xV", A[motor_num(xv)]) + epics_put ("X04SA-ES3-MOT:y1", A[motor_num(y1)]) + epics_put ("X04SA-ES3-MOT:y2", A[motor_num(y2)]) + epics_put ("X04SA-ES3-MOT:y3", A[motor_num(y3)]) + epics_put ("X04SA-ES3-MOT:TRx", A[motor_num(trx)]) + epics_put ("X04SA-ES3-MOT:thetaY", A[motor_num(thy)]) + #epics_put ("X04SA-ES3-MOT:Slit1", A[motor_num(s1)]) + #epics_put ("X04SA-ES3-MOT:Slit2", A[motor_num(s2)]) + #epics_put ("X04SA-ES3-MOT:Slit3", A[motor_num(s3)]) + #epics_put ("X04SA-ES3-MOT:Slit4", A[motor_num(s4)]) + #epics_put ("X04SA-ES3-MOT:Slit5", A[motor_num(s5)]) + #epics_put ("X04SA-ES3-MOT:Slit6", A[motor_num(s6)]) + #epics_put ("X04SA-ES3-MOT:Slit7", A[motor_num(s7)]) + #epics_put ("X04SA-ES3-MOT:Slit8", A[motor_num(s8)]) + + epics_put ("X04SA-ES3-SPEC:H", Q[0]) + epics_put ("X04SA-ES3-SPEC:K", Q[1]) + epics_put ("X04SA-ES3-SPEC:L", Q[2]) + epics_put ("X04SA-ES3-SPEC:LAMBDA", Q[4]) + # Then dump the EPICS channels + if ($# < 1) { + myFile = epics_get ("X04SA-ES3-CCD:FNAM") + myFile = substr (myFile, 0, index (myFile, ".")) + myFile = sprintf ("%s%s%s", PIX_LOG, myFile, "pxl") + } else { + myFile = sprintf ("%s%s", PIX_LOG, "$1") + } + myCmnd = sprintf (PIX_LOG_CMND, myFile) + unix (myCmnd) + } +}' + +#+ +#------------------------------------------------------------------------------ +# Controling the shutter on the detector arm +# ------------------------------------------ +# +# pshop - open the shutter on the detector arm +# pshcl - close the shutter on the detector arm +# +#- + +def pshop 'epics_put ("X04SA-ES3-PINO:PS-SET", "Out")' +def pshcl 'epics_put ("X04SA-ES3-PINO:PS-SET", "In")' + +#+ +#------------------------------------------------------------------------------ +# Internal routines +# ----------------- +# +# pixCheckFileFmt - check that file format contains a string +# of the form "%0...d" or "%0...i". +#- + +def pixCheckFileFmt (fmt, verbose) '{ +# =============== + + idx = index (fmt, "%") + if (idx <= 0) { + if (verbose) { + print "\aWarning -- file template does not contain a \"%0...d\" string." + } + return 1 + } else { + idx = idx + 1 + if (substr (fmt, idx, 1) == "i") return 0 + if (substr (fmt, idx, 1) == "d") return 0 + if (substr (fmt, idx, 1) != "0") { + if (verbose) { + print "\aWarning -- the character after \"%\" should be \"0\", \"i\" or \"d\"." + } + return 1 + } + i = sscanf (substr (fmt, idx), "%d%c", _1, _2) + if ((i != 2) || ((_2 != "i") && (_2 != "d"))) { + if (verbose) { + print "\aWarning -- file template does not contain a valid \"%0...d\" string." + } + return 1 + } + } + return 0 +}' + +#+ +#------------------------------------------------------------------------------ +# pixgetfilefmt - retrieve the image file format from the name template. +# set global variable PIX_FILE_HEADER_LENGTH accordingly. +#- + +def pixgetfilefmt '{ +# ============= + + # get the file name extension and set the file type dependent parameters + my_fmt = epics_get(PIX_FNAM_FMT_CHN) + nitem = split(my_fmt,my_fileparts,".") + my_ext = my_fileparts[nitem-1] + + if (my_ext == "tif"){ + PIX_FILE_HEADER_LENGTH = 4096 + } else if (my_ext == "edf") { + PIX_FILE_HEADER_LENGTH = 1024 + } else { + PIX_FILE_HEADER_LENGTH = 0 + } + + # update corresponding variables for the image analysis + IMAGE_HEADER_LENGTH = PIX_FILE_HEADER_LENGTH +}' + + +#+ +#------------------------------------------------------------------------------ +#- +#============================================================================== +# +##################################################### +# 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: pixel.mac,v $ +# Revision 1.11 2009/05/28 10:10:56 schlepuetz +# removed Pilatus1 support, check image file format during count command to allow for img,edf,tif files +# +# Revision 1.10 2009/05/27 15:00:41 bjorck +# Adding changes for EPICS implementation of motors and fixes for the hexapod +# +# Revision 1.9 2007/02/21 09:06:28 maden +# Remove references to s1, ..., s8 +# +# Revision 1.8 2007/02/21 08:56:57 maden +# Send sms message if status time-out +# +# Revision 1.7 2006/12/13 15:04:11 schlepuetz +# removed requirement that exposuretime must be an integer multiple of 0.001 seconds in pixsetexpose +# +# Revision 1.6 2006/07/07 11:49:56 maden +# Modify PIX_LOG_CMND command +# +# Revision 1.5 2006/06/16 08:48:33 schlepuetz +# fixed typo on pixhelp +# +# Revision 1.4 2006/06/14 11:44:28 schlepuetz +# fixed bug in pixUserCountEnd returning the wrong COUNT_ID value (1 too high). +# +# Revision 1.3 2006/03/01 13:02:47 maden +# Check-in newer version from /work ... +# +# Revision 1.2 2005/11/30 15:34:19 schlepuetz +# fixed timing problem with pixlogwrite; resolved issues with pixwait running into timeouts for long exposures +# +# Revision 1.1 2005/11/10 11:15:20 schlepuetz +# first tested version of this file +# +# +#============================== End of $RCSfile: pixel.mac,v $=== \ No newline at end of file diff --git a/script/spec/sdStartup.py b/script/spec/sdStartup.py new file mode 100644 index 0000000..e674887 --- /dev/null +++ b/script/spec/sdStartup.py @@ -0,0 +1,427 @@ +#============================================================================== +# Macroname: sdStartup.mac +# ============= +# +# $Date: 2009/05/28 10:09:21 $ +# $Header: /cvs/G/SPEC/local/X04SA/ES3/sdStartup.mac,v 1.10 2009/05/28 10:09:21 schlepuetz Exp $ +#+ +# $Source: /cvs/G/SPEC/local/X04SA/ES3/sdStartup.mac,v $ +# $Revision: 1.10 $ +# +# Description: specialized startup macro for the surface diffraction station. +# includes all setup routines required to use the pixel detector. +# +# Note: +# +# Author(s): C. M. Schlepuetz (CS) +# Co-author(s): 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/06/10 +# +#- +# Chained macro definitions affected by this macro: +# ------------------------------------------------- +# - none +# +# Change Log: +# ----------- +# +# 2005/06/10 (CS): +# - created the first version of this macro. +# +# 2005/11/30 (CS): +# - modified sdStartup to make sure that no previous experiment is still active +# when starting a new one. +# +# 2006/04/24 (CS): +# - changed call to 'setsample' (which was part of the hkl-workaround) to +# 'startgeo'. +# +# 2006/08/08 (CS): +# - avoid that a logfile is overwritten if sdStartup is called twice with the +# same logfile name. Now, information is appended to an existing logfile. +# - included call to scanlist.mac in sdStartup. +# +# 2008/02/20 (CS): +# - removed links to 'specmacros' and 'scanlogs' in directory tree. This led to +# confusion and sometimes the duplication of the data if links were not +# followed correctly by backup software. +# +# 2008/02/21 (CS): +# - removed 'archives' directory under 'pixel' +# - renamed 'analyzed_data' to 'analysis_runtime' +# +# 2009/05/27 (CS): +# - enable scanlists and scanlogs by default (remove user option to turn it on) +# - force use of pixel detector (shortened setup routine) +# +# 2009/05/28 (CS): +# - change permissions of pixel directory recursively by 'a+w' automatically +# when created (chmod -R a+w pixel). +# +#============================================================================== +# + global SD_STARTUP_MAC +# + SD_STARTUP_MAC = DOFILE # Save the name of this macro file. + _sav_geo_mot = 1 # spec's global variable used by setscans macro +#+ +#============================================================================== +# This macro file contains the following commands: +#- +# +#+ +#------------------------------------------------------------------------------ +# sdStartuphelp - generates this help text. This is obtained by +# displaying the file sd_startup.txt, which should sit in +# the same directory as this file. +#- + +def helpSdStartup 'sdStartuphelp' +def sdStartupHelp 'sdStartuphelp' +def sdstartuphelp 'sdStartuphelp' + +def sdStartuphelp '{ +# ============= + + unix (sprintf ("dirname %s", _MAC), _1) + ll = length (_1) + if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1)) + file = sprintf ("%s/sms.txt", _1) + if (file_info (file, "-e")) { + unix (sprintf ("cat %s | less", file)) + } else { + printf ("\n Macros available in file sd_startup.mac ($Revision: 1.10 $):\n") + print " ==============" + print "" + print " sdStartuphelp - creates this help text" + print " sdStartup - startup routine for the surface diffraction" + print " station. Sets all important parameters and" + print " paths." + print " sdShutdown - shutdown routine for the surface diffraction" + print " station. Resets all paths and filenames to" + print " standard values to prevent writing to" + print " experiment-specific files." + } +}' + +#+ +#------------------------------------------------------------------------------ +# sdStartup - startup procedure for the surface diffraction station. +# It sets up important parameters and the data storage +# environment for the experiment. Experimental data is +# stored in the following directory structure: +# +# [] +# `-- +# |-- analysis_runtime # on-the-fly analysis during experiments +# |-- archive # backup directory for experimental data (zip) +# | |-- images # zip-files of images +# | |-- imagelogs # zip-files of imagelogs +# |-- fotos # fotos of experimental setup, etc. +# |-- pixel # pixel detector related information +# | |-- flatfield # flatfield data +# | | |-- flatfield(1) # 1st flatfield data set +# | | |-- flatfield(2) # 2nd flatfield data set +# | | `-- ... # ... +# | |-- imagelogs # logfiles for each individual pixel image +# | |-- images # the pixel detector images themselves +# |-- software # user made software (i.e. shell scripts, etc.) +# | |-- matlab # matlab routines for data analysis +# | |-- shell_scripts # shell scripts +# `-- spec # SPEC related information +# |-- logs # logfiles (.spec, .log, etc.) +# |-- scanlogs # log files for each individual scan +# `-- specmacros # working directory for user made SPEC macros +# +# is set during the startup procedure. If the user is running +# from an e-account, the above directory tree is created inside the e-account +# directory (i.e. e10003//pixel/...) +#- + +def sdStartup '{ +# ========= + + global DATAFILE, LOGFILE, DO_DIR + global TITLE, COUNT, UPDATE + global SDSTARTUP_ON, SDSTARTUP_PROJECT + + local dataBaseDir, expBaseDir, pixelBaseDir + local eAccount, projectDirName, _dir + local _append, _cont + local specFile + + dataBaseDir = "/sls/X04SA/data/" + expBaseDir = "/sls/X04SA/data/x04sa/ES3/expdata/" + pixelBaseDir = "/sls/X04SA/data/x04sa/ES3/pixel/" + tmpLog = "/tmp/tmpLog.spec" + + def sdStartupCleanupOnce \' + tty_cntl("se") + \' + cdef("cleanup_once","sdStartupCleanupOnce;","sdStartup_cleanup_once_key") + + + if(SDSTARTUP_ON){ + printf("Currently, the following experiment is still active:\n%s\n", \\ + SDSTARTUP_PROJECT) + tty_cntl("so") + if(yesno("Close the active experiment and start a new one?",0)){ + tty_cntl("se") + close(DATAFILE) + close(LOGFILE) + } else{ + tty_cntl("se") + printf("Startup routine aborted...\n") + exit + } + } + +# turn on logging to a temporary file (this will be moved to +# the projects permanent log file later). + on(tmpLog) + +#------------------------------- +# get information on the project + tty_cntl("so") + if(yesno("Are you using an e-account?",0) == 1){ + eAccount=getsval("Please enter your e-account name \(i.e. e10003\)") + } + else{ + eAccount="" + } + tty_cntl("se") + + _cont=0 + while(_cont==0){ + printf("\nPlease enter a name for your project\'s data directory ending ") + printf("with the current\ndate in the following format: _yyyymmdd") + printf("\(e.g., Ni111_20050226\)\n") + tty_cntl("so") + projectDirName=getsval("Project name:","") + tty_cntl("se") + # set up the project directory + if(eAccount != ""){ + _dir=sprintf("%s%s/%s/",dataBaseDir,eAccount,projectDirName) + } + else{ + _dir=sprintf("%s%s/",expBaseDir,projectDirName) + } + + printf("\nYour project directory name is:\n %s\n",projectDirName) + tty_cntl("so") + if(yesno("Is that o.k.?",1)){ + _cont=1 + } + tty_cntl("se") + if(file_info(_dir,"-d")== 1){ + printf("\nDirectory %s already exists!\n", _dir) + printf("It contains the following items:\n") + unix(sprintf("ls -g --color %s",_dir)) + tty_cntl("so") + if(yesno("Change your project name?",1)==0){ + _cont=1 + _append=1 + } else{ + _cont=0 + } + tty_cntl("se") + } + } + printf("\nYour data will be stored in\n %s\n", _dir) + SDSTARTUP_PROJECT = projectDirName + +#---------------------------------- +# set up the project directory tree + + cmd_file="/tmp/startup_cmd.sh" + unix(sprintf("rm -f %s",cmd_file)) + open(cmd_file) + fprintf(cmd_file,"mkdir %s\n", _dir) + fprintf(cmd_file,"cd %s\n", _dir) + fprintf(cmd_file,"mkdir spec pixel fotos software analysis_runtime ") + fprintf(cmd_file,"archive \n") + fprintf(cmd_file,"# create subdirs of archive\n") + fprintf(cmd_file,"cd archive; mkdir images imagelogs; cd ..\n") + fprintf(cmd_file,"# create subdirs of spec\n") + fprintf(cmd_file,"cd spec; mkdir logs scanlogs specmacros; cd ..\n") + fprintf(cmd_file,"# create subdirs of pixel\n") + fprintf(cmd_file,"cd pixel; mkdir images imagelogs ") + fprintf(cmd_file,"flatfield; cd ..\n") + fprintf(cmd_file,"# create subdirs of software\n") + fprintf(cmd_file,"cd software; mkdir matlab shell_scripts; cd ..\n") + fprintf(cmd_file,"# change permissions on pixel directory\n") + fprintf(cmd_file,"chmod -R a+w pixel\n") + close(cmd_file) + unix(sprintf("chmod 700 %s; %s",cmd_file,cmd_file)) + unix(sprintf("rm -f %s",cmd_file)) + + printf("directory structure:\n") + unix(sprintf("tree %s",_dir),_tmp) + print _tmp #this ensures that the tree appears in the log file + + # set working directory + chdir(sprintf("%s%s",_dir,"spec/specmacros")) + DO_DIR=sprintf("%s%s",_dir,"spec/specmacros") + + # open the spec file + specFile=sprintf("%sspec/logs/%s.spec",_dir,projectDirName) + eval(sprintf("newfile %s 0",specFile)) + + # turn on the log file and copy + # contents of temporary log into it. + LOGFILE=sprintf("%sspec/logs/%s.log",_dir,projectDirName) + close(tmpLog) + if(file_info(LOGFILE,"-e")){ + # if logfile already exists, append contents of temporary file to the end. + open(LOGFILE) + fprintf(LOGFILE,"\n\n-----------------------------------------------\n\n") + close(LOGFILE) + unix(sprintf("cat %s >> %s",tmpLog,LOGFILE)) + unix(sprintf("rm -f %s",tmpLog)) + } else{ + unix(sprintf("mv %s %s",tmpLog,LOGFILE)) + } + on(LOGFILE) + + tty_cntl("so") + TITLE=getsval("\nTitle for scan headers (i.e. sample name)",TITLE) + COUNT = getval("Default count time for ct and uct",COUNT) + UPDATE = getval("Update interval for umv, uct, etc. in seconds",UPDATE) + tty_cntl("se") + + # set geometry parameters + printf("\nSet the geometry parameters: \(startgeo\)\n") + startgeo + + # set scan options + printf("\nSet some scan options: \(setscans\)\n") + setscans + + # enable scanlogs + if (SCANLOG_MAC){ + eval(sprintf("scanlogSetPath %s%s", _dir,"spec/scanlogs/")) + scanlogOn + } + + # enable scanlist + if (SCANLIST_MAC){ + eval(sprintf("scanlistFilename %s%s",_dir,"spec/logs/scanlist.txt")) + scanlistOn + } + + # set plot options + printf("\nSet some plotting options: \(setplot\)\n") + setplot + + # set up the pixel detector as default detector + printf("\nSet up the PILATUS Pixel detector\n") + if(eAccount != ""){ + eprint "e-Accounts are not yet supported in conjunction with the pixel" + eprint "detector. This is due to write permission errors and will be" + eprint "resolved with the new generation of the pixel detector control" + eprint "software. Please contact your user-supporter if you encounter" + eprint "this problem here." + exit + } else{ + pixFilePath = sprintf("%s%s%s","../../expdata/",projectDirName,\\ + "/pixel/images/") + eval(sprintf("pixsetup %s",pixFilePath)) # run the setup routine + pixon # enable the pixel detector + # turn on logging for each image taken to standard path: + pixLogPath = sprintf("%s%s", _dir,"pixel/imagelogs/") + eval(sprintf("pixlogon %s", pixLogPath)) + } + + printf("\n%s\n%s\n%s\n",\\ + "Your experiment has been set up successfully. Please remember to",\\ + "run \'sdShutdown\' after completing your measurements to prevent",\\ + "other users from accidentally modifying your experimental data.") + + SDSTARTUP_ON = 1 + cdef("cleanup_once","","sdStartup_cleanup_once_key","delete") + +}' + +#+ +#------------------------------------------------------------------------------ +# sdShutdown - Cleanup procedure to be executed after an experiment. +# Experimental files are closed and logging is redirected +# to some standard files. The entire experimenal environ- +# ment used before is abandoned by SPEC. +#- + +def sdShutdown '{ +# ========== + + global DATAFILE, LOGFILE, DO_DIR + + # reset the current working directory to standard location + chdir(sprintf("%s","~/specmacros")) + + # close the SPEC data file and reopen the standard file. + close(DATAFILE) + eval(sprintf("newfile %s 0","/sls/X04SA/data/x04sa/ES3/tmp/dummy.spec")) + + # close the SPEC log file and reset the global variable to the standard value + close(LOGFILE) + LOGFILE = "/sls/X04SA/data/x04sa/ES3/tmp/dummy.log" + + # redirect pixel detector output to standard locations + pixsetpath "tmp/" + pixlogoff + + SDSTARTUP_ON = 0 + +}' + +#+ +#------------------------------------------------------------------------------ +#- +##################################################### +# 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: sdStartup.mac,v $ +# Revision 1.10 2009/05/28 10:09:21 schlepuetz +# change permissions on pixel directory automatically by a+w +# +# Revision 1.9 2009/05/27 15:59:36 schlepuetz +# shortened setup routine +# +# Revision 1.8 2008/02/21 09:59:25 schlepuetz +# updated documentation +# +# Revision 1.7 2008/02/21 09:55:35 schlepuetz +# removed archives directory under pixel, renamed analyzed_data to analysis_runtime +# +# Revision 1.6 2008/02/20 09:10:13 schlepuetz +# removed links to specmacros and scanlogs in directory tree +# +# Revision 1.5 2006/08/11 10:34:10 schlepuetz +# improved output formatting of sdStartup +# +# Revision 1.4 2006/08/08 14:07:38 schlepuetz +# prevent overwrite of old log files, added enable/disble of scanlist +# +# Revision 1.3 2006/05/04 10:15:23 schlepuetz +# call startgeo instead of setsample +# +# Revision 1.2 2005/11/30 15:33:11 schlepuetz +# modified sdStartup to make sure that no previous experiment is still active when starting a new one. +# +# Revision 1.1 2005/11/10 11:24:07 schlepuetz +# first tested version of this file +# +# +#============================= End of $RCSfile: sdStartup.mac,v $ === \ No newline at end of file diff --git a/script/spec/site_f.py b/script/spec/site_f.py new file mode 100644 index 0000000..86747a9 --- /dev/null +++ b/script/spec/site_f.py @@ -0,0 +1,1592 @@ +#============================================================================== +# Macroname: site_f.mac +# ========== +#+ +# $Date: 2009/05/27 15:52:34 $ +# $Author: schlepuetz $ +# $Source: /cvs/G/SPEC/local/X04SA/ES3/site_f.mac,v $ +# $Revision: 1.13 $ +# $Tag: $ +# +# Description: Macro for declaring site-dependent macro functions. "site_f.mac" +# is automatically read and executed if SPEC is started for the +# first time or invoked with the -f ("fresh") option. +# +# Note: This is the version of "site_f.mac" specific to the ISSD (ES3) +# station of the X04SA beamline at SLS. +# For definitions and commands that need to be run at every +# startup of SPEC, see "site.mac". +# +# Installed location: +# $SLSBASE/sls/spec/local/X04SA/ES3/site_f.mac +# with a symbolic link from +# $SPECD/site_f.mac +# via the command: +# ln -s $SLSBASE/sls/spec/local/X04SA/ES3/site_f.mac $SPECD/site_f.mac +# +# Author: D. Maden (DM) +# Co-author(s): C.M. Schlepuetz (CS) +# Address: Surface Diffraction Station +# Materials Science Beamline X04SA +# Swiss Light Source (SLS) +# Paul Scherrer Institut +# CH - 5232 Villigen PSI +# Created: 2005/07/20 +# +#- +# Macro definitions which are changed with respect to standard.mac: +# ----------------------------------------------------------------- +# - home # include homing for epics motors as well +# - ascan # include scans with the hexapod - removed by MB +# - count_em # use the EPICS DCR508 scaler +# - count # expanded functionality used by other site-specific +# macros +# - ct # expanded functionality used by other site-specific +# macros +# - waitcount # include the EPICS DCR508 scaler +# - get_counts # include the EPICS DCR508 scaler +# - _timescan # include call to 'scan_tail' at the end +# - hklscan # ignore points with unphysical HKL values and continue +# - _hklline # ignore points with unphysical HKL values and continue +# +# New macro definitions: +# ---------------------- +# - mvhkl # interactive call to 'br' so user can confirm move +# - recount # repeat exposure upon criteria in chk_counts +# - issd_scan_hdr_on # turn on ISSD header in data file +# - issd_scan_hdr_on # turn off ISSD header in data file +# - issd_filehead # writes the ISSD file header to the data file +# - issd_scan_head # writes the ISSD scan header to the data file +# - issd_scan_tail # writes the ISSD scan tail to the data file +# +# Chained macro definitions affected by site_f.mac: +# ----------------------------------------------- +# - user_Fheader (in issd_scan_hdr_on, issd_scan_hdr_off) +# - user_scan_tail (in issd_scan_hdr_on, issd_scan_hdr_off) +# - cleanup_once (in ct) +# +# Global variables defined in site_f.mac: +# ------------------------------------- +# SLSBASE, SLSCONFIG, SITE_F_DIR, COMMON_DIR +# COUNT_ID +# +# Change Log of site_f.mac: +# ----------------------- +# 2009/02-03 (MB): +# - Commented out the ascan definition +# - Addded hex_on to +# +# +# 2005/10/10 (CS): +# - Added more header information and comments to the code +# - Added 'recount' macro +# - modified 'count' and 'ct' macros to improve functionality and readability +# - included many more X04SA specific macros to be read at startup +# - introduced the global variable COUNT_ID to store some sort of ID number for +# the last exposure (for image detectors, this should be the last image +# number) +# - call the H,K,L macros to assure the global variable Q is initialized. +# +# 2005/11/07 (CS): +# - reduced sleep time in waitcount to 0.05 seconds. +# +# 2005/11/09 (CS): +# - changed site.mac (which was read and executed every time SPEC is +# restarted) to (this) site_f.mac. This is only read and executed when SPEC +# is started for the first time or invoked with the -f ("fresh") option, +# thus preserving the current status of all macro definitions (including +# chained macros) when SPEC is started normally. +# (This used to cause problems with chained macros being overwritten by +# site.mac while the associated global variables where preserved. In the case +# of a fresh start, these global variables are also cleared, resulting in a +# consistent system.) +# +# 2005/12/13 (CS): +# - added a fourth treshold level for automatic filter and exposure time +# settings if auto.mac is available and auto mode is enabled in get_counts +# +# 2006/05/04 (CS): +# - added macro definitions for 'mvhkl' and 'umvhkl'. +# - added modified macro definition for 'hklscan' and '_hklline' which allow +# the skipping of unobtainable points in reciprocal space rather than +# aborting the scan completely. +# - load orient.mac at startup +# - Dave's hkldefs.mac and Christian's hklscans.mac are only loaded for specSD +# and specOptics +# +# 2006/08/08 (CS): +# - improved output of 'mvhkl' and 'umvhkl'. +# - load scanlist.mac at startup +# - added modified macro definition for '_timescan' which includes a call to +# 'scan_tail' at the end to enable execution of user-defined cleanup tasks. +# +# 2008/02/15 (CS): +# - load plot.mac at startup +# +# 2009/05/27 (MB): +# - Adding changes for EPICS implementation of motors and fixes for the +# hexapod: +# - commented out custom version of 'ascan' +# - added macro definitions 'home', '_ksepicsmotor', 'ksmotor' +# - Execute the parameter handling definitions from X12SA Oliver Bunk +# - issue 'hex_on' command at startup +# +# 2009/05/27 (CS): +# - load wigglercheck.mac on startup +# +#============================================================================== +# +#------------------------------------------------------------------------------ +# Ensure that SLSBASE and SLSCONFIG are set. +# Then execute the common SLS macro file, if it can be found. +# + global SLSBASE, SLSCONFIG, SITE_F_DIR, COMMON_DIR + + SLSBASE = "" + unix ("echo -n \$SLSBASE", SLSBASE) + + SLSCONFIG = "" + unix ("echo -n \$SLSCONFIG", SLSCONFIG) + # + # Find directory containing site_f.mac. This involves + # the resolution of a symbolic link. Define + # SITE_F_DIR and COMMON_DIR accordingly. + _1 = "dummy" + unix (sprintf ("readlink %s/%s", SPECD, "site_f.mac"), _1) + if (_1 != "" ) { + SITE_F_DIR = "dummy" + unix (sprintf ("dirname %s", _1), SITE_F_DIR) + sscanf (SITE_F_DIR, "%s", SITE_F_DIR) # Remove trailing newline. + COMMON_DIR = "dummy" + unix (sprintf ("cd %s; cd ../../common; pwd", SITE_F_DIR), COMMON_DIR) + sscanf (COMMON_DIR, "%s", COMMON_DIR) # Remove trailing newline + } else { + SITE_F_DIR = sprintf ("%s/sls/spec/local/X04SA/ES3", SLSBASE) + COMMON_DIR = sprintf ("%s/sls/spec/local/common", SLSBASE) + } + + file = sprintf ("%s/sls-common.mac", COMMON_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } + +#+ +#============================================================================== +# This macro file contains the following macro definitions: +#- +# +#+ +#------------------------------------------------------------------------------ +# home - alternative version of standard home to allow +# homing of epics motors +#- +# +def home ' + if ($# < 1 || $# > 3) { + eprint "Usage: home motor [+|-] [home_pos]" + exit + } + _check0 "$1" + waitmove + ifp { fprintf(PRINTER,"\n$*\n") } + + if ("$1" == "phi"){ + printf("Homing phi through EPICS...\n") + # Workaround to have relaiable operation + mvr phi 0.1 + waitmove + epics_put("X04SA-ES3-XPS:PHI.HOMR", 1) + exit + } + if ("$1" == "oh"){ + printf("Homing omegaH through EPICS...\n") + # Workaround to have relaiable operation + mvr oh 0.1 + waitmove + epics_put("X04SA-ES3-XPS:OMEGAH.HOMR", 1) + exit + } + if ("$1" == "nu"){ + printf("Homing nu through EPICS...\n") + # Workaround to have relaiable operation + mvr nu 0.1 + waitmove + epics_put("X04SA-ES3-XPS:NU.HOMR", 1) + exit + } + if ("$1" == "ov"){ + printf("Homing omegaV through EPICS...\n") + # Workaround to have relaiable operation + mvr ov 0.1 + waitmove + epics_put("X04SA-ES3-XPS:OMEGAV.HOMR", 1) + exit + } + if ("$1" == "alp"){ + printf("Homing alpha through EPICS...\n") + # Workaround to have relaiable operation + mvr alp 0.1 + waitmove + epics_put("X04SA-ES3-XPS:ALPHA.HOMR", 1) + exit + } + if ("$1" == "del"){ + printf("Homing delta through EPICS...\n") + # Workaround to have relaiable operation + mvr del 0.1 + waitmove + epics_put("X04SA-ES3-XPS:DELTA.HOMR", 1) + exit + } + if ("$1" == "gam"){ + printf("Homing gamma through EPICS...\n") + # Workaround to have relaiable operation + mvr gam 0.1 + waitmove + epics_put("X04SA-ES3-XPS:GAMMA.HOMR", 1) + exit + } + if ("$1" == "xv"){ + printf("Homing xV through EPICS...\n") + # Workaround to have relaiable operation + mvr xv 0.1 + waitmove + epics_put("X04SA-ES3-XPS:XV.HOMR", 1) + exit + } + if ("$1" == "y1"){ + printf("Homing y1 through EPICS...\n") + # Workaround to have relaiable operation + mvr y1 0.1 + waitmove + epics_put("X04SA-ES3-XPS:Y1.HOMR", 1) + exit + } + if ("$1" == "y2"){ + printf("Homing y2 through EPICS...\n") + # Workaround to have relaiable operation + mvr y2 0.1 + waitmove + epics_put("X04SA-ES3-XPS:Y2.HOMR", 1) + exit + } + if ("$1" == "y3"){ + printf("Homing y3 through EPICS...\n") + # Workaround to have relaiable operation + mvr y3 0.1 + waitmove + epics_put("X04SA-ES3-XPS:Y3.HOMR", 1) + exit + } + if ("$1" == "trx"){ + printf("Homing trx through EPICS...\n") + # Workaround to have relaiable operation + mvr trx 0.1 + waitmove + epics_put("X04SA-ES3-XPS:TRX.HOMR", 1) + exit + } + if ("$1" == "hx"){ + printf("Homing hx through EPICS...\n") + # Workaround to have relaiable operation + epics_put("X04SA-ES3-HXP:TRX.HOMR", 1) + exit + } + if ("$1" == "hy"){ + printf("Homing hy through EPICS...\n") + # Workaround to have relaiable operation + epics_put("X04SA-ES3-HXP:TRY.HOMR", 1) + exit + } + if ("$1" == "hz"){ + printf("Homing hz through EPICS...\n") + # Workaround to have relaiable operation + epics_put("X04SA-ES3-HXP:TRZ.HOMR", 1) + exit + } + if ("$1" == "hrox"){ + printf("Homing hrox through EPICS...\n") + # Workaround to have relaiable operation + epics_put("X04SA-ES3-HXP:ROX.HOMR", 1) + exit + } + if ("$1" == "hroy"){ + printf("Homing hroy through EPICS...\n") + # Workaround to have relaiable operation + epics_put("X04SA-ES3-HXP:ROY.HOMR", 1) + exit + } + if ("$1" == "hroz"){ + printf("Homing hroz through EPICS...\n") + # Workaround to have relaiable operation + epics_put("X04SA-ES3-HXP:ROZ.HOMR", 1) + exit + } + else{ + if ($# == 1) + chg_dial($1, "home") + else if ($# == 2) { + if ("$2" == "+") + chg_dial($1, "home+") + else if ("$2" == "-") + chg_dial($1, "home-") + else + chg_dial($1, "home", eval("$2+0")) + } else if ($# == 3) { + if ("$2" == "+") + chg_dial($1, "home+", $3) + else if ("$2" == "-") + chg_dial($1, "home-", $3) + else { + eprint "Usage: home motor [+|-] [home_pos]" + exit + } + } + } + + move_poll +' +#+ +#------------------------------------------------------------------------------ +# ksmotor - kickstart an epicsmotor by going through the STOP PAUSE MOVE GO +# sequence + +def _ksepicsmotor(motor)'{ + ks_sleep_time = 0.5 + + epics_put(motor, 0) + sleep(ks_sleep_time) + epics_put(motor, 1) + sleep(ks_sleep_time) + epics_put(motor, 2) + sleep(ks_sleep_time) + epics_put(motor, 3) +}' + +def ksmotor '{ + + if ($# != 1) { + eprint "Usage: ksmotor motor" + eprint "Used to kickstart a locked epics motor by doing an epics" + eprint "START STOP MOVE GO sequence which can unlock freezed motors" + exit + } + if ("$1" == "phi"){ + _ksepicsmotor("X04SA-ES3-XPS:PHI.SPMG") + exit + } + if ("$1" == "oh"){ + _ksepicsmotor("X04SA-ES3-XPS:OMEGAH.SPMG") + exit + } + if ("$1" == "nu"){ + _ksepicsmotor("X04SA-ES3-XPS:NU.SPMG") + exit + } + if ("$1" == "ov"){ + _ksepicsmotor("X04SA-ES3-XPS:OMEGAV.SPMG") + exit + } + if ("$1" == "alp"){ + _ksepicsmotor("X04SA-ES3-XPS:ALPHA.SPMG") + exit + } + if ("$1" == "del"){ + _ksepicsmotor("X04SA-ES3-XPS:DELTA.SPMG") + exit + } + if ("$1" == "gam"){ + _ksepicsmotor("X04SA-ES3-XPS:GAMMA.SPMG") + exit + } + if ("$1" == "xv"){ + _ksepicsmotor("X04SA-ES3-XPS:XV.SPMG") + exit + } + if ("$1" == "y1"){ + _ksepicsmotor("X04SA-ES3-XPS:Y1.SPMG") + exit + } + if ("$1" == "y2"){ + _ksepicsmotor("X04SA-ES3-XPS:Y2.SPMG") + exit + } + if ("$1" == "y3"){ + _ksepicsmotor("X04SA-ES3-XPS:Y3.SPMG") + exit + } + if ("$1" == "trx"){ + _ksepicsmotor("X04SA-ES3-XPS:TRX.SPMG") + exit + } + else{ + eprint "Motor does not support kickstarting" + } +}' + +#------------------------------------------------------------------------------ +# ascan - alternative version of standard ascan to allow +# hexapod scans available too. +#- +# +#def ascan '{ +# ===== +# +# global _m, _s, _f, _n1, _ctime +# +# if ($# != 5) { +# eprint "Usage: ascan motor start finish intervals time" +# exit +# } +# print "Got here" +# if (("$1" == "xx") || \ +# ("$1" == "yy") || \ +# ("$1" == "zz") || \ +# ("$1" == "uu") || \ +# ("$1" == "vv") || \ +# ("$1" == "ww")) { +# checkHexLim $1 $2 $3 +# _m[0] = "$1"; _s[0] = $2; _f[0] = $3 +# _n1 = int ($4); _ctime = $5 +# _nm = 1 +# _hexascan +# } else { +# _check0 "$1" +# _m[0] = $1; _s[0] = $2; _f[0] = $3 +# _n1 = int ($4); _ctime = $5 +# _nm = 1 +# _ascan +# } +# }' +# +#+ +#------------------------------------------------------------------------------ +# count_em - lowest level counting macro. Modify the +# version in standard.mac to get it to use the +# EPICS DCR508 scaler. +#- + +def count_em '{ +# ======== + local cnt_stat + + # Mythen I0 + while (epics_get ("X04SA-ES2-SD1:cam1:Acquire") != "Done") { + epics_put("X04SA-ES2-SD1:cam1:Acquire", "Done") + sleep(0.25) + } + + COUNT_TIME = $#?($1):COUNT + user_precount + + if (COUNT_TIME != 0) { + if (COUNT_TIME > 0) { + # MYTHEN + epics_put("X04SA-ES2-SD1:cam1:AcquireTime", COUNT_TIME) + epics_put("X04SA-ES2-SD1:cam1:ImageMode", "Single") + epics_put("X04SA-ES2-SD1:cam1:Acquire", "Acquire") + }else { + print "Preset monitor counting is not supported\!" + } + } + user_postcount + }' + +#+ +#------------------------------------------------------------------------------ +# count - second lowest level count command. +# This version is slightly expanded with respect to +# the original definitio_asca_ascan in standard.mac: +# count_end, chk_counts, and chk_xray have been +# added to provide further flexibility +# regarding the use of various detectors. +# +# Note: count_em is something like a "count_start" and triggers the counting +# process but does not wait for its completion. +# The 'user_postcount' routine in 'count_em' is therefore more something +# like a "user_whilecount". The 'count_end' macro included in this +# definition of 'count' is intended to provide a real post-count +# facility. +# 'chk_counts' and 'chk_xray' can be used to verify whether the count +# process has delivered satisfactory data and whether the x-ray beam +# has been available and sufficiently intense during counting. +# 'chk_beam' is a slightly misleading name, its purpose is to terminate +# the counting process when all criteria for a successful count are +# met. This is done with the included 'break' statement which terminates +# the enclosing for-loop in 'count' +#- + +def count '{ +# ===== + + waitmove + if ($1) for (;;) { + count_em $1 # triggers the counting process + waitcount # waits for counting to finish + count_end # clean up after counting + get_counts # retrieve the counts from detectors + chk_xray # verify quality of xray + chk_counts # verify quality of counts + chk_beam # terminate this count loop + } + if (S[sec] && MON >= 0) + MON_RATE=S[MON]/S[sec] +}' + +# define new count_end, chk_counts, and chk_xray macros: +def count_end 'user_count_end' +def chk_counts 'user_chk_counts' +def chk_xray 'user_chk_xray' +# use the EPICS DCR508 scaler +# initially, user_count_end, user_chk_counts, and user_chk_xray are empty: +def user_count_end '' # if used, this should be a chained macro definition +def user_chk_counts '' # if used, this should be a chained macro definition +def user_chk_xray '' # if used, this should be a chained macro definition + +#+ +#------------------------------------------------------------------------------ +# ct - second lowest level count command - for manual count. +# This version is slightly expanded with respect to +# the original definition in standard.mac: +# count_end has been added to provide further +# flexibility regarding the use of various detectors. +# +# Note: See also the description of the modified 'count' command for more +# information. +#- + +def ct '{ +# == + + cdef("cleanup_once", "onp; show_cnts; offp; user_ct", "ct") + waitmove + count_em $1 # triggers the counting process + waitcount # waits for counting to finish + count_end # clean up after counting + cdef("cleanup_once", "", "ct", "delete") + onp; show_cnts; offp + user_ct + +}' + +#+ +#------------------------------------------------------------------------------ +# recount - allows to retake the last data point - useful when +# files (images) need to be overwritten. Include +# device-specific code in user_pre_recount and +# user_post_recount. +# +# Note: This is essentially a modified version of count +# without the check commands (chk_xray, chk_counts, +# and chk_beam) at the end. +#- + +def recount '{ +# ======= + + waitmove + user_pre_recount # should be a chained macro definition + count_em $1 # triggers the counting process + waitcount # waits for counting to finish + count_end # clean up after counting + get_counts # retrieve the counts from detectors + user_post_recount # should be a chained macro definition +}' + +# initially, user_pre_recount and user_post_recount are empty. +def user_pre_recount '' +def user_post_recount '' + +#+ +#------------------------------------------------------------------------------ +# waitcount - waits for counting to stop +#- + +def waitcount '{ +# ========= + local cnt_stat + local i + + user_waitcount + + # MYTHEN + i = 0 + while (epics_get ("X04SA-ES2-SD1:cam1:Acquire") != "Done") { + sleep (0.05) + i += 1 + if (i * 0.05 >= COUNT_TIME * 2) { + print "MYTHEN Izero times out, status: " epics_get("X04SA-ES2-SD1:cam1:DetectorState_RBV") + break + } + } + }' + +#+ +#------------------------------------------------------------------------------ +# get_counts - lowest level counter reading macro. +#- + +def get_counts '{ +# ========== + + S[0] = epics_get ("X04SA-ES2-SD1:cam1:AcquireTime") + S[1] = epics_get ("X04SA-ES2-SD1:Stats5:Total_RBV") + # S[2] is detector counts from image.mac + S[3] = S[2] / COUNT_TIME / epics_get("X04SA-ES2-FI:TRANSM") + + S[5] = epics_get ("X04SA-ES2-FI:TRANSM") + + COUNT_ID++ # increment the exposure ID + + # set threshold counts in case auto-level support is available + if ((whatis("AUTO_THRESH1") & 0x08000000) == 0) { + AUTO_THRESH1_COUNT = (S[2]>=AUTO_THRESH1)?S[2]:0 + AUTO_THRESH2_COUNT = (S[2]>=AUTO_THRESH2)?S[2]:0 + AUTO_THRESH3_COUNT = (S[2]>=AUTO_THRESH3)?S[2]:0 + AUTO_THRESH4_COUNT = (S[2]>=AUTO_THRESH4)?S[2]:0 + } + + user_getcounts +}' + +#+ +#------------------------------------------------------------------------------ +# mvhkl - modified version of \'br\' which displays the angle +# positions of the requested hkl-position first and asks +# for the users confirmation to move there before the +# movement is started. +# +# Usage: +# mvhkl +# or mvhkl auto +# +#- + def mvhkl '{ +# ===== + + getangles + old_A = A + + auto = 0 + if ($# != 3) { + if (($# == 4) && ("$4" == "auto")) { + auto = 1 + } else{ + print "\aUsage:" + print " mvhkl " + print " or mvhkl auto" + exit + } + } + + H = $1; K = $2; L = $3 + + # calcA returns 0 for success, -1 for unobtainable reflection + possible = !(-(calcA)) + + if(possible) { + if (auto != 1) { + for (i=0;i<_numgeo;i++) { + s = motor_name(mA[i]) + printf ("%7s = %9.4f --> %9.4f\n", s, old_A[mA[i]], A[mA[i]]) + } + ok = 1 + ok = yesno ("Move to these values? ", ok) + } else{ + ok = 1 + } + if (ok) { + br $1 $2 $3 + } else{ + print "Move abandoned." + exit + } + } + }' + +#+ +#------------------------------------------------------------------------------ +# umvhkl - modified version of \'ubr\' which displays the angle +# positions of the requested hkl-position first and asks +# for the users confirmation to move there before the +# movement is started. +# +# Usage: +# umvhkl +# or umvhkl auto +# +#- + + def umvhkl '{ +# ====== + + getangles + old_A = A + + auto = 0 + if ($# != 3) { + if (($# == 4) && ("$4" == "auto")) { + auto = 1 + } else{ + print "\aUsage:" + print " mvhkl " + print " or mvhkl auto" + exit + } + } + + H = $1; K = $2; L = $3 + + # calcA returns 0 for success, -1 for unobtainable reflection + possible = !(-(calcA)) + + if(possible) { + if (auto != 1) { + for (i=0;i<_numgeo;i++) { + s = motor_name(mA[i]) + printf ("%7s = %9.4f --> %9.4f\n", s, old_A[mA[i]], A[mA[i]]) + } + ok = 1 + ok = yesno ("Move to these values? ", ok) + } else { + ok = 1 + } + if (ok) { + ubr $1 $2 $3 + } else { + print "Move abandoned." + exit + } + } + }' + + +#+ +#------------------------------------------------------------------------------ +# _timescan - low-level timescan macro. +# Added call to 'scan_tail' in the end. For a normal +# time scan, which is usually ended by a Ctrl+C, this +# has no effect at all. However, 'loopscan' uses +# '_timescan' and terminates itself after a certain +# number of counting loops. The addition of 'scan_tail' +# to '_timescan' ensures that 'loopscan' performs the +# normal user-defined cleanup tasks for scans in the end +# (like closing scanlogs for example). +#- + +def _timescan ' +# ========= + + if ($# > 1) _ctime = $2; else _ctime = COUNT + if ($# > 2) _stime = $3; else _stime = 0 + + HEADING = sprintf("%s %g %g", HEADING, _ctime, _stime) + _cols = 1 + _sx = 0; _fx= _ctime>0 ? 20*(_ctime + _stime + _sleep) : 5 + X_L = "Time" + Y_L = cnt_name(DET) + _stype = 16 + FPRNT="Time " + PPRNT=sprintf("%8.8s ", "Time") + VPRNT=sprintf("%9.9s ", "Time") + _n1 = int($1) + scan_head + _n1 = 0 + def _scan_on \'{ + local _time maxPTS shft + maxPTS = array_op("rows", SCAN_D) + shft = maxPTS/2 + for (; int($1) == 0 || NPTS < int($1); NPTS++) { + if (NPTS - _n1 >= maxPTS){ + SCAN_D[0:(maxPTS - shft - 1)][] = SCAN_D[shft:(maxPTS - 1)][] + _n1 += shft + } + _time = time()-TIME + FPRNT=sprintf("%g ",_time) + PPRNT=sprintf("%8.4g ",_time) + VPRNT=sprintf("%9.4f ",_time) + scan_loop + scan_data(NPTS-_n1, _time) + if (_time > _fx) { + local val + val = NPTS + # will cause scan_plot to refresh + NPTS = 0 + _fx += 0.1 * (_fx - _sx) + _sx = SCAN_D[1][0] + scan_plot + NPTS = val + } + scan_plot + do_sleep _stime + } + scan_tail + }\' + TIME=time() + _scan_on +' + +#+ +#------------------------------------------------------------------------------ +# hklscan - low-level reciprocal space scan macro. +# Modified such that the scan skips points corresponding +# to physically unobtainable reflections in reciprocal +# space without trying to move or count. +# This will reduce the number of errors due to aborted +# scans and prevents long series of several scans to +# crash out. +#- + +def hklscan ' +# ======= + + if ($# != 8) { + eprint "\ +Usage: hklscan Hstart Hfinish Kstart Kfinish Lstart Lfinish intervals time" + exit + } + { + _s1 = $1; _f1 = $2; _s2 = $3; _f2 = $4; _s3 = $5; _f3 = $6 + _n1 = int($7); _ctime = $8 + } + + if (_n1 <= 0) { + eprint "Intervals <= 0" + exit + } + HEADING = sprintf("hklscan %g %g %g %g %g %g %g %g", $1,$2,$3,\ + $4,$5,$6,$7,$8) + _d1 = (_f1 - _s1)/_n1 + _d2 = (_f2 - _s2)/_n1 + _d3 = (_f3 - _s3)/_n1++ + + H=_f1; K=_f2; L=_f3 + calcA; _bad_lim=0; _hkl_lim + if (_bad_lim) { + eprintf("(H K L = %g %g %g)\n",H,K,L) + exit + } + if (_pre_chk) { + local i + for (i=0;i<_n1;i++) { + H = _s1 + i*_d1 + K = _s2 + i*_d2 + L = _s3 + i*_d3 + calcA + _bad_lim = 0 + _hkl_lim + if (_bad_lim) { + eprintf("(H K L = %g %g %g)\n",H,K,L) + exit + } + } + } + _cols=3 + if (_sav_geo_mot) + _cols += _numgeo + if (_d3) + { X_L = "L"; _sx = _s3; _fx = _f3 } + else if (_d2) + { X_L = "K"; _sx = _s2; _fx = _f2 } + else + { X_L = "H"; _sx = _s1; _fx = _f1 } + Y_L = cnt_name(DET) + _stype = 2 + FPRNT="H K L " + PPRNT="" + { + local i, s + for (i=0;i<_numgeo;i++) { + s = motor_name(mA[i]) + PPRNT = PPRNT sprintf("%8.8s ",s) + if (_sav_geo_mot) + FPRNT = FPRNT s " " + } + } + VPRNT=sprintf("%10s %10s %10s ","H","K","L") + scan_head + def _scan_on \' + for (; NPTS < _n1; NPTS++) { + local i h_ca k_ca l_ca _bad_hkl + H = h_ca = _s1 + NPTS*_d1 + K = k_ca = _s2 + NPTS*_d2 + + L = l_ca = _s3 + NPTS*_d3 + get_angles; + _bad_hkl = calcA + _bad_lim = 0 + _hkl_lim + if((_bad_hkl == 0) && (_bad_lim == 0)){ + scan_move + FPRNT=sprintf("%g %g %g ",h_ca,k_ca,l_ca) + PPRNT="" + for (i=0;i<_numgeo;i++) { + PPRNT = PPRNT sprintf("%8.4f ",A[mA[i]]) + if (_sav_geo_mot) + FPRNT = FPRNT sprintf("%.8g ",A[mA[i]]) + } + VPRNT=sprintf("%10.5g %10.5g %10.5g ",h_ca,k_ca,l_ca) + scan_loop + scan_data(NPTS,_d3? l_ca:(_d2? k_ca:h_ca)) + H=h_ca; K=k_ca; L=l_ca + scan_plot + } + else{ + printf("(H, K, L = %g %g %g)\n",H,K,L) + } + } + scan_tail + \' + _scan_on +' + +#+ +#------------------------------------------------------------------------------ +# _hklline - low-level reciprocal space scan macro. +# Modified such that the scan skips points corresponding +# to physically unobtainable reflections in reciprocal +# space without trying to move or count. +# This will reduce the number of errors due to aborted +# scans and prevents long series of several scans to +# crash out. +# +# Note: This macro is used in other reciprocal space scan macros like +# \'hkcircle\'. +#- + +def _hklline ' +# ======== + + {_const = $1; _s1 = $2; _f1 = $3; _n1 = int($4); _ctime = $5} + + if (_n1 <= 0) { + eprint "Intervals <= 0" + exit + } + + _d1 = (_f1 - _s1) / _n1++ + _cols=4 + if (_sav_geo_mot) + _cols += _numgeo + _sx = _s1; _fx = _f1 + Y_L = cnt_name(DET) + _stype = 2 + FPRNT=sprintf("%s H K L ",X_L) + PPRNT="" + { + local i, s + for (i=0;i<_numgeo;i++) { + s = motor_name(mA[i]) + PPRNT = PPRNT sprintf("%8.8s ",s) + if (_sav_geo_mot) + FPRNT = FPRNT s " " + } + } + VPRNT=sprintf("%10s %10s %10s ","H","K","L") + + { + local x + x = _f1 + _hkl x + if ("$6" != "0") + $6 + calcA + _bad_lim = 0 + _hkl_lim + if (_bad_lim) { + eprintf("(H K L = %g %g %g)\n", H, K, L) + exit + } + } + if (_pre_chk) for (i=0; i<_n1; i++) { + local x + x = _s1 + i * _d1 + _hkl x + if ("$6" != "0") + $6 + calcA + _bad_lim = 0 + _hkl_lim + if (_bad_lim) { + eprintf("(H K L = %g %g %g)\n", H, K, L) + exit + } + } + + scan_head + def _scan_on \' + for (; NPTS < _n1; NPTS++) { + local i x h_ca k_ca l_ca + _x = _s1 + NPTS * _d1 + _hkl _x + if ("$6" != "0") + $6 + h_ca = H; k_ca = K; l_ca = L + get_angles; + if(calcA == 0){ + scan_move + FPRNT=sprintf("%g %g %g %g ",_x,h_ca,k_ca,l_ca) + PPRNT="" + for (i=0;i<_numgeo;i++) { + PPRNT = PPRNT sprintf("%8.4f ",A[mA[i]]) + if (_sav_geo_mot) + FPRNT = FPRNT sprintf("%.8g ",A[mA[i]]) + } + VPRNT=sprintf("%10.5g %10.5g %10.5g ",h_ca,k_ca,l_ca) + scan_loop + scan_data(NPTS,_x) + H = h_ca; K = k_ca; L = l_ca + scan_plot + } + else{ + printf("(H, K, L = %g %g %g)\n",H,K,L) + #printf("move not possible - skipped scan point\n") + } + } + scan_tail + \' + _scan_on +' + + + +#+ +#------------------------------------------------------------------------------ +# issd_scan_hdr_on - redefine user scan macros to get the +# ISSD (In-Situ Surface Diffractometer) +# stuff included. +#- + +def issd_scan_hdr_on '{ +# ================ + + def user_filehead \'issd_filehead\' + if (DATAFILE != "") { + fprintf (DATAFILE, "#C ISSD scan headers turned on at %s\n", date()) + user_filehead; off (DATAFILE); on ("tty") + } + + undef user_Fheader + cdef ("user_Fheader", "issd_scan_head;", "key-0") + + undef user_scan_tail + cdef ("user_scan_tail", "issd_scan_tail;", "key-0") +}' + +#+ +#------------------------------------------------------------------------------ +# issd_scan_hdr_off - revert to normal scan macros. +#- + +def issd_scan_hdr_off '{ +# ================= + + def user_filehead \'\' + + undef user_Fheader + cdef ("user_Fheader") + + undef user_scan_tail + cdef ("user_scan_tail") + + if (DATAFILE != "") { + fprintf (DATAFILE, "#C ISSD scan headers turned off at %s\n", date()) + } +}' + +#+ +#------------------------------------------------------------------------------ +# issd_filehead - write some ISSD stuff to the data file every +# time it is opened +#- + +def issd_filehead '{ +# ============= + + fprintf (DATAFILE, "#C ISSD header information\n") + fprintf (DATAFILE, "#C EPICS Channels \"#UE ...\"\n") + fprintf (DATAFILE, "#UE ARIDI- PCT:CURRENT\n") + fprintf (DATAFILE, "#UE X04SA- ID-GAP:READ\n") + fprintf (DATAFILE, "#UE X04SA-FE- BM1:TRH.RBV BM1:TRV.RBV BM2:TRH.RBV BM2:TRV.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP- FI1:TR1.RBV FI2:TR1.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-BM1 TRX.RBV TRY.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-MOX1 ROX.RBV ROZ.RBV TRY.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-MOX2 ROX.RBV ROY.RBV ROZ.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-MOX2 TRX.RBV TRY.RBV TRYA.RBV TRYB.RBV TRYC.RBV TRYD.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-BM2: TRX.RBV TRY.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-MI1 TRX1.RBV TRY1.RBV TRY2.RBV TRY3.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-MI2 TRY1.RBV TRY2.RBV TRY3.RBV TR3D.RBV TR3U.RBV\n") + fprintf (DATAFILE, "#UE X04SA-OP-BM3: TRX.RBV TRY.RBV\n") + fprintf (DATAFILE, "#UE X04SA-EH1- SH1:TR1.RBV SH1:TR2.RBV SV1:TR1.RBV SV1:TR2.RBV\n") + fprintf (DATAFILE, "#UE X04SA-EH2- SH1:TR1.RBV SV1:TR2.RBV SV1:TR1.RBV SH1:TR2.RBV\n") + fprintf (DATAFILE, "#UE X04SA-ES3- SH1:TR1.RBV SH1:TR2.RBV SV1:TR1.RBV SV1:TR2.RBV\n") + fprintf (DATAFILE, "#UE X04SA-ES3- SH2:TR1.RBV SH2:TR2.RBV SV2:TR1.RBV SV2:TR2.RBV\n") + fprintf (DATAFILE, "#UE X04SA-ES3- SH3:TR1.RBV SH3:TR2.RBV SV3:TR1.RBV SV3:TR2.RBV\n") + fprintf (DATAFILE, "#UE X04SA-ES3- FI1:SET FI2:SET FI3:SET FI4:SET FI5:SET FI6:SET FI7:SET FI8:SET\n") + fprintf (DATAFILE, "#UE X04SA-ES3- FI9:SET FI10:SET FI11:SET FI12:SET FI13:SET FI14:SET FI15:SET FI16:SET\n") + fprintf (DATAFILE, "#UE \"\" H K L LAMBDA\n") + }' + +#+ +#------------------------------------------------------------------------------ +# issd_scan_head - scan header macro to put ISSD specific items +# into scan header. +#- + +def issd_scan_head '{ +# ============== + + array my_arr[100] + local i, j + + i = 0 + my_arr[i] = epics_get ("ARIDI-PCT:CURRENT"); i++ + my_arr[i] = epics_get ("X04SA-ID-GAP:READ"); i++ + my_arr[i] = epics_get ("X04SA-FE-BM1:TRH.RBV"); i++ + my_arr[i] = epics_get ("X04SA-FE-BM1:TRV.RBV"); i++ + my_arr[i] = epics_get ("X04SA-FE-BM2:TRH.RBV"); i++ + my_arr[i] = epics_get ("X04SA-FE-BM2:TRV.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-FI1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-FI2:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-BM1:TRX.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-BM1:TRY.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX1:ROX.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX1:ROZ.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX1:TRY.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:ROX.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:ROZ.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:ROY.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRX.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRZ.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRY.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRYA.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRYB.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRYC.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MOX2:TRYD.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-BM2:TRX.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-BM2:TRY.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI1:TRX1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI1:TRY1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI1:TRY2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI1:TRY3.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI2:TRY1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI2:TRY2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI2:TRY3.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI2:TR3D.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-MI2:TR3U.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-BM3:TRX.RBV"); i++ + my_arr[i] = epics_get ("X04SA-OP-BM3:TRY.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH1-SH1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH1-SH1:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH1-SV1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH1-SV1:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH2-SH1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH2-SV1:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH2-SV1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-EH2-SH1:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SH1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SH1:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SV1:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SV1:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SH2:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SH2:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SV2:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SV2:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SH3:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SH3:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SV3:TR1.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES3-SV3:TR2.RBV"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI1:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI2:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI3:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI4:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI5:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI6:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI7:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI8:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI9:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI10:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI11:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI12:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI13:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI14:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI15:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI16:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI17:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI18:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI19:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI20:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI21:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI22:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI23:SET", "float"); i++ + my_arr[i] = epics_get ("X04SA-ES2-FI24:SET", "float"); i++ + my_arr[i] = Q["0"]; i++ + my_arr[i] = Q["1"]; i++ + my_arr[i] = Q["2"]; i++ + my_arr[i] = Q["4"]; i++ + for (j = 0; j < i; j = (j + 8)) { + str = sprintf ("#UH%d", j/8) + for (k = 0; ((k < 8) && ((j + k) < i)); k++) + str = sprintf ("%s %.5f", str, my_arr[j+k]) + fprintf (DATAFILE, "%s\n", str) + } + }' + +#+ +#------------------------------------------------------------------------------ +# issd_scan_tail - scan header macro to put ISSD specific items into +# tail of scan data. +#- + +def issd_scan_tail '{ +# ============== + + array my_arr[10] + local i, j + + i = 0 + my_arr[i] = epics_get ("ARIDI-PCT:CURRENT"); i++ + my_arr[i] = epics_get ("X04SA-ID-GAP:READ"); i++ + + fprintf (DATAFILE, sprintf ("#UT0 %.5f %.5f\n", my_arr[0], my_arr[1])) + }' + + +#============================================================================== +#-----------------------------------------------------------------------------# +# Execute macro definitions defined in additional macro files. # +#-----------------------------------------------------------------------------# + +#-------------------------------------------------------- +# Execute the Surface Diffraction help macro definitions +# + file = sprintf ("%s/sdHelp.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#------------------------------------------------------------ +# Execute the additional orientation matrix macro definitions +# + file = sprintf ("%s/orient.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#------------------------------------- +# Execute the filter macro definitions +# + file = sprintf ("%s/filter.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#---------------------------------- +# Execute the ccd macro definitions +# + file = sprintf ("%s/ccd.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#---------------------------------------------------- +# Execute ccd macro definitions +# + file = sprintf ("%s/ccdscanlog.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------- +# Execute the hexapod macro definitions +# + file = sprintf ("%s/hexapod.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------- +# Execute the id gap macro definitions +# + file = sprintf ("%s/id.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------- +# Execute the slits macro definitions +# + file = sprintf ("%s/slits.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#----------------------------------------------------- +# Execute the PILATUS pixel detector macro definitions +# + file = sprintf ("%s/pixel.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#--------------------------------------------- +# Execute the image analysis macro definitions +# + file = sprintf ("%s/image.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the filter transmission and exposure time +# automatization macro definitions +# + file = sprintf ("%s/auto.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the scanlist macro definitions +# + file = sprintf ("%s/scanlist.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the scanlog macro definitions +# + file = sprintf ("%s/scanlog.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the plot macro definitions +# + file = sprintf ("%s/plot.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the shutter macro definitions +# + file = sprintf ("%s/shutter.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the cyberstar macro definitions +# + file = sprintf ("%s/cyber.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the beamblocker macro definitions +# + file = sprintf ("%s/beamblock.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the SMS messaging service macro definitions +# + file = sprintf ("%s/sms.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the surface diffraction startup macro definitions +# + file = sprintf ("%s/sdStartup.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the move macro definitions +# + file = sprintf ("%s/move.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the parameter handling definitions from X12SA Oliver Bunk +# + file = sprintf ("%s/parameter_handling.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the wigglercheck macro definitions +# + file = sprintf ("%s/wigglercheck.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } +#-------------------------------------------------- +# Execute the misc macro definitions +# + file = sprintf ("%s/misc.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } + +#------------------------------------------------------------------- +# Load up some ESRF macros +# + file = sprintf ("/import%s/sls/spec/esrf/local/macros/xscans.mac", \ + SLSBASE) + if (file_info (file, "-f")) { + qdofile (file) + } else { + file = sprintf ("%s/sls/spec/esrf/local/macros/xscans.mac", \ + SLSBASE) + if (file_info (file, "-f")) { + qdofile (file) + } else { + printf ("\aWarning -- cannot find ESRF macros \"xscans.mac\".\n") + } + } +# - - - - - - - - - - - - - - - - - + file = sprintf ("/import%s/sls/spec/esrf/local/macros/lineup.mac", \ + SLSBASE) + if (file_info (file, "-f")) { + qdofile (file) + } else { + file = sprintf ("%s/sls/spec/esrf/local/macros/lineup.mac", \ + SLSBASE) + if (file_info (file, "-f")) { + qdofile (file) + } else { + printf ("\aWarning -- cannot find ESRF macros \"lineup.mac\".\n") + } + } +#------------------------------------------------------------------- +# For specSD and specOptics: +# Undefine the standard reciprocal space macros and +# execute the hand-made macro definitions. +# + if ((SPEC == "specSD") || (SPEC == "specOptics")) { + file = sprintf ("%s/hkldefs.mac", SITE_F_DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } + file = sprintf ("%s/hklscans.mac", SITE_F_DIR) + p file + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } + } +#-------------------------------------------------------- +# For specOptics: +# Execute the Lakeshore macro definitions just for +# specOptics (used by Fabia for testing when pc3197 +# is occupied). +# + if (SPEC == "specOptics") { + + SITE_F_ES2DIR = "dummy" + unix (sprintf ("dirname %s", SITE_F_DIR), SITE_F_ES2DIR) + sscanf (SITE_F_ES2DIR, "%s", SITE_F_ES2DIR) # Remove trailing newline. + SITE_F_ES2DIR = SITE_F_ES2DIR "/ES2" + + file = sprintf ("%s/lakeshore.mac", SITE_F_ES2DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } + + file = sprintf ("%s/PDmisc.mac", SITE_F_ES2DIR) + if (file_info (file, "-f")) { + DOFILE = file; qdofile (file) + } + } + +#============================================================================== +# Issue some commands at startup +# + global COUNT_ID # initiate global variable COUNT_ID which holds the + # ID number of the last exposure (for images, this + # should be set to the current image number in the + # get_counts routine) + COUNT_ID=1 # initialize COUNT_ID with a value of 1 + + H=0;K=0;L=0 # initialize the Q array to [0,0,0] + + issd_scan_hdr_on # Make sure the ISSD headers are on by default. + printf ("\nISSD scan headers have been turned on.\n") + + shon # activate automatic shutter control. + shcl # close the fast photon shutter. + printf("Fast photon shutter is in automatic mode. Type \'shStatus\' for info.\n") + +# printf("\n") + + autoInit # make sure auto-level global vars are initialized + + cyberOn # Make sure the cyberstar point detector is activated + # and set some important global vars. + + + cvs_revision = "$Revision: 1.13 $" + cvs_revision = substr (cvs_revision, index (cvs_revision, " ") + 1) + cvs_revision = substr (cvs_revision, 0, index (cvs_revision, " ") - 1) + printf ("Revision %s of the X04SA/ES3 site_f.mac file has been executed.\n", cvs_revision) + + if (SPEC == "s2d2") { + printf ("\a\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n", \ + "+-------------------------------------------------------+", \ + "| Note on Motors for s2d2: s2d2 Name ISSD Name |", \ + "| ======================= ========= ========= |", \ + "| gam gamma |", \ + "| del delta |", \ + "| ** PROVISIONAL ** chi alpha |", \ + "| phi omegaV |", \ + "+-------------------------------------------------------+") + } + +#+ +#------------------------------------------------------------------------------ +#- +#============================================================================== +# +##################################################### +# 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: site_f.mac,v $ +# Revision 1.13 2009/05/27 15:52:34 schlepuetz +# load wigglercheck on startup, updated changelog +# +# Revision 1.12 2009/05/27 15:00:41 bjorck +# Adding changes for EPICS implementation of motors and fixes for the hexapod +# +# Revision 1.11 2008/02/15 09:10:17 schlepuetz +# load plot.mac at startup +# +# Revision 1.10 2007/01/22 15:20:36 maden +# Add qdo of xscans.mac and lineup.mac +# +# Revision 1.9 2006/08/08 14:06:41 schlepuetz +# modified macro definition of _timescan to include a scan_tail at the end, improved mvhkl and umvhkl, load scanlist.mac at startup, updated header info +# +# Revision 1.8 2006/05/04 09:54:01 schlepuetz +# help text cosmetics... +# +# Revision 1.7 2006/05/04 09:47:09 schlepuetz +# added mvhkl,umvhkl,hklscan,_hklline macro defs; load orient.mac at startup +# +# Revision 1.6 2006/03/03 07:06:27 maden +# Rename lakeshore-by-Dante.mac +# +# Revision 1.5 2006/03/01 12:53:45 maden +# Add some specials for specOptics +# +# Revision 1.4 2006/03/01 11:00:27 maden +# Add a fourth treshold level for automatic filter ... +# +# Revision 1.3 2005/11/11 10:43:38 schlepuetz +# typo on line 18... +# +# Revision 1.2 2005/11/11 07:43:03 schlepuetz +# added hklscans.mac to be read at startup. +# +# Revision 1.1 2005/11/10 11:29:05 schlepuetz +# this is an identical copy of and replaces the old site.mac +# +# +#============================= End of $RCSfile: site_f.mac,v $ === \ No newline at end of file diff --git a/script/test/DetectorTriggering.py b/script/test/DetectorTriggering.py new file mode 100644 index 0000000..87e688d --- /dev/null +++ b/script/test/DetectorTriggering.py @@ -0,0 +1,142 @@ +def count (count_time): + waitmove + count_em (count_time) # triggers the counting process + waitcount # waits for counting to finish + count_end # clean up after counting + get_counts # retrieve the counts from detectors + chk_xray # verify quality of xray + chk_counts # verify quality of counts + chk_beam # terminate this count loop + if (S[sec] && MON >= 0) + MON_RATE=S[MON]/S[sec] + + + + +def count_em (count_time): +# ======== + while (mythen.is_acquiring()): + mythen.stop() + time.sleep(0.25) + + user_precount() + + if (count_time != 0): + if (count_time > 0): + # MYTHEN + mythen.set_acquire_time(count_time) + mythen.set_acquire_mode("Single") + mythen.start() + else: + print "Preset monitor counting is not supported\!" + user_postcount() + + + +# define new count_end, chk_counts, and chk_xray macros: +def count_end 'user_count_end' +def chk_counts 'user_chk_counts' +def chk_xray 'user_chk_xray' +# use the EPICS DCR508 scaler +# initially, user_count_end, user_chk_counts, and user_chk_xray are empty: +def user_count_end '' # if used, this should be a chained macro definition +def user_chk_counts '' # if used, this should be a chained macro definition +def user_chk_xray '' # if used, this should be a chained macro definition + +#+ +#------------------------------------------------------------------------------ +# ct - second lowest level count command - for manual count. +# This version is slightly expanded with respect to +# the original definition in standard.mac: +# count_end has been added to provide further +# flexibility regarding the use of various detectors. +# +# Note: See also the description of the modified 'count' command for more +# information. +#- + +def ct (count_time): +# == + + cdef("cleanup_once", "onp; show_cnts; offp; user_ct", "ct") + waitmove + count_em (count_time) # triggers the counting process + waitcount # waits for counting to finish + count_end # clean up after counting + cdef("cleanup_once", "", "ct", "delete") + onp; show_cnts; offp + user_ct + +}' + +#+ +#------------------------------------------------------------------------------ +# recount - allows to retake the last data point - useful when +# files (images) need to be overwritten. Include +# device-specific code in user_pre_recount and +# user_post_recount. +# +# Note: This is essentially a modified version of count +# without the check commands (chk_xray, chk_counts, +# and chk_beam) at the end. +#- + +def recount '{ +# ======= + + waitmove + user_pre_recount # should be a chained macro definition + count_em $1 # triggers the counting process + waitcount # waits for counting to finish + count_end # clean up after counting + get_counts # retrieve the counts from detectors + user_post_recount # should be a chained macro definition +}' + +# initially, user_pre_recount and user_post_recount are empty. +def user_pre_recount '' +def user_post_recount '' + +#+ +#------------------------------------------------------------------------------ +# waitcount - waits for counting to stop +#- + +def waitcount(count_time): + user_waitcount() + + i = 0 + while (mythen.is_acquiring()): + sleep (0.05) + i += 1 + if (i * 0.05 >= count_time * 2): + print "MYTHEN Izero times out, status: " + str(mythen.get_status()) + break + +#+ +#------------------------------------------------------------------------------ +# get_counts - lowest level counter reading macro. +#- + +def get_counts(): +# ========== + + S[0] = mythen.get_acquire_time(readback=False) + S[1] = mythen.get_total_counts() + # S[2] is detector counts from image.mac + S[3] = S[2] / COUNT_TIME / epics_get("X04SA-ES2-FI:TRANSM") + + S[5] = epics_get ("X04SA-ES2-FI:TRANSM") + + COUNT_ID++ # increment the exposure ID + + # set threshold counts in case auto-level support is available + if ((whatis("AUTO_THRESH1") & 0x08000000) == 0) { + AUTO_THRESH1_COUNT = (S[2]>=AUTO_THRESH1)?S[2]:0 + AUTO_THRESH2_COUNT = (S[2]>=AUTO_THRESH2)?S[2]:0 + AUTO_THRESH3_COUNT = (S[2]>=AUTO_THRESH3)?S[2]:0 + AUTO_THRESH4_COUNT = (S[2]>=AUTO_THRESH4)?S[2]:0 + } + + user_getcounts +}'