esrf

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

#%TITLE% Monochromator tuning
#%NAME%
#  Macros for automatic monochromator tuning.
#
#%CATEGORY% Tools
#
#%OVERVIEW%
#  To be written.
#
#%EXAMPLE%
#
#  %DL%
#  %DT%monotunesetup
#  %DD%Configures ...
#  %DT%monotune on
#  %DD%
#  %XDL%
#%END%

#%UU%  <motor_mne> [<counter_mne>] [<period> [<step>]] [scans] [<macro>]
#%MDESC%
#
#
def monotunesetup '{
   global MONOTUNE
   local par parlist n tint tstep err mode motmne monnme cmd drop

   parlist[0]=""
   n = split("$*", parlist)
   err = mode = 0
   motmne = monmne = ""
   tint = tstep = -1
   for (i = 0; i < n; i++) {
      par = parlist[i]
      newerr = 0
      if (par == "all") {
         mode |= 0x01
      } else if (whatis(par) & 2) {          # macro name
         rdef monotuneit par
      } else if (par+0 != par) {
         if (motor_num(par) >= 0)            # motor mnemonic
            motmne = par
         else if (cnt_num(par) >= 0)         # counter mnemonic
            monmne = par
         else
            newerr = 1
      } else if (tint < 0) {
         tint = par
      } else if (tstep < 0) {
         tstep = par
      } else {
         newerr = 1
      }
      if (newerr) {
         err ++
         if (SETUP)
            printf("Wrong parameter \`%s\' in line: $0 $*\n", par)
         else
            printf("Wrong parameter \`%s\'\n", par)
      }

   }

   if (err || motmne=="") {
     print "Usage:  monotune motor_mne [counter_mne] [interval [step]] [\"scans\"] [macro]"
   } else {
      MONOTUNE["motor"] = motmne
      MONOTUNE["monitor"] = monmne? monmne : cnt_mne(MON)
      MONOTUNE["interval"] = (tint > 0)? tint : 600
      MONOTUNE["tstep"] = (tstep > 0)? tstep : COUNT
      MONOTUNE["last"] = time()
      #by default no percentage adjustment, just time
      MONOTUNE["i0trigger"]=0
      MONOTUNE["i0factor"]=0.80
      cmd = (mode & 0x01)? "_monotune(\"?\")\n" : \
                           "if(_stype & 32) _monotune(\"?\");;\n"
      cdef("measure0", cmd, "monotune", 0x10)

      user_monotunesetup

      if (MONOTUNE["disabled"])
         cdef("", "", "monotune", "disable")

      setup_tail("monotune")
   }
}'

#%UU% 
#%MDESC%
#
#
def monotuneunsetup '{
   unglobal MONOTUNE
   cdef("", "", "monotune", "delete")
}'

#%UU% "?" | [<monitor> [<time_step>]]
#%MDESC%
#
#
def monotune '{
   global MONOTUNE
   local monmne monomon answ

   _stype = 0
   if ("$1" == "?") {
      _monotune("?")
   } else {
      monnme = ($#)? "$1":MONOTUNE["monitor"]
      while ((monomon = cnt_num(monnme)) < 0 || monomon == monnme ) {
         printf("\nCounter mnemonic \`%s\' is not valid.\n", monnme)
         answ = getval("Enter beam monitor mnemonic or \`?\' for help", \
                           cnt_mne(MON))
         if (answ == "?") {
            print "Currently defined mnemonics:"
            for (i = 0; i < COUNTERS; i++) printf("\t%s", cnt_mne(i))
            print
         } else
            monnme = answ
      }
      _monotune(monomon, $2)
   }
}'

#%UU% [factor]
#%MDESC%
#%PRE%
# Turns on intensity triggering:
# After the time specified in monotunesetup, il will check if
# detector_value < (factor * old_peak_maximum) prior to autotune
# if so, it will autotune
# if not, it will wait the time specified in monotunesetup prior
# to check again
# DANGER: if there is a new refill, the intensity may be always above
# the last value and tuning might never be done
# Therefore, if detector_value > (1.05 * old_peak_maximum) autotune 
# performed
#%PRE%
def monotuneonintensityon '
   MONOTUNE["i0trigger"]=1
   if ($#) {
        if ($1 > 0.0) {
            MONOTUNE["i0factor"]=$1
        }
   }
print "Monochromator intensity triggering is ON."
#printf("Current threshold for autotuning is %f\n",\
#                MONOTUNE["i0factor"]*GHRES["peak_count"])
print "Use \`monotuneonintensityoff\' to trigger only on time."
'

#%UU%
#%MDESC%
#%PRE%
# Turns off intensity triggering:
# After the time specified in monotunesetup, il will check if
# detector_value < (factor * old_peak_maximum) prior to autotune
# if so, it will autotune
# if not, it will wait the time specified in monotunesetup prior
# to check again
# DANGER: if there is a new refill, the intensity may be always above
# the last value and tuning might never be done
# Therefore, if detector_value > (1.05 * old_peak_maximum) autotune 
# performed
#%PRE%
def monotuneonintensityoff '
   MONOTUNE["i0trigger"]=0
print "Monochromator intensity triggering is OFF."
print "Use \`monotuneonintensityon\' to trigger on intensity."
'


#%UU%
#%MDESC%
#
#
def monotuneon '
   MONOTUNE["disabled"] = 0
   cdef("", "", "monotune", "enable")
   print "Monochromator autotuning is ON. Use \`monotuneoff\' to switch off."
'

#%UU%
#%MDESC%
#
#
def monotuneoff '
   MONOTUNE["disabled"] = 1
   cdef("", "", "monotune", "disable")
   print "Monochromator autotuning is OFF."
'

#%IU% ("?" | <monitor>, [<time_step>])
#%MDESC%
#
#
def _monotune(monomon, monotime) '{
   local monmne monomotor monostep
   local i0 iinit posinit phase

   if ((monomotor = motor_num(MONOTUNE["motor"])) < 0) {
      fprintf("tty", \
            "Motor \`%s\' not configured. Monochromator tuning cancelled!", \
            MONOTUNE["motor"])
      return(-1)
   } 

   if (monomon == "?") {
      if (time() < MONOTUNE["last"] + MONOTUNE["interval"] || \
          MONOTUNE["disabled"] ||                          \
          (monomon = cnt_num(MONOTUNE["monitor"])) < 0) {
         return(0)
      }
      if (!BEAMCHK_ON) {
         print "Warning. Beam checking is not switched on. Use \`onbeamchk\'."
      }
   }

   if (_stype & 1) {
      for (i = 0; i < _stype>>8; i++) {
         if (_m[i] == monomotor) {
            print "Scanning monochromator motor. Autotuning cancelled."
            MONOTUNE["last"] = time()
            return(-2)
         }
      }
   }
   
   if(MONOTUNE["i0trigger"]){
        #print "monomon = ",monomon
        #print "tstep = ",MONOTUNE["tstep"]
        #print "S[monomon] before = ",S[monomon]
        #print S[0]
        count MONOTUNE["tstep"]
        #print "S[monomon] after = ",S[monomon]
        #print S[0]
        #print "i0factor = ",MONOTUNE["i0factor"]
        #print "peak_count = ",GHRES["peak_count"]
        if (S[monomon] < (1.05 * GHRES["peak_count"])){
            if (S[monomon] > (MONOTUNE["i0factor"] * GHRES["peak_count"])){
                MONOTUNE["last"]=time()
                printf("%f > %f * %f = %f Not autonuning it\n",S[monomon],\
                					MONOTUNE["i0factor"],GHRES["peak_count"],\
                          MONOTUNE["i0factor"] * GHRES["peak_count"])
                return(0)
            }
        } 
   }
   if (!MONOTUNE["dmthmax"]) MONOTUNE["dmthmax"] = 1
   if (monotime <= 0)
      monotime = (MONOTUNE["tstep"] > 0)? MONOTUNE["tstep"] : COUNT
   monostep = 1/motor_par(monomotor, "step_size")
   monotuneit
   MONOTUNE["last"] = time()
}'

if (!(whatis("monotuneit") & 2)) rdef monotuneit "stepping_monotune"

if (!(whatis("user_monotunesetup") & 2)) rdef user_monotunesetup ""

# Local variables:
#  monomotor - motor number
#  monomon   - counter number
#  monotime  - counting time
#  monostep  - move step
#
def stepping_monotune '
   monmne = cnt_mne(monomon)
   while (1) {
      fprintf("tty", "\nMonochromator tuning.  Monitor: \`%s\'  Time: %g sec.\n",\
             monmne, monotime)
      fprintf("tty", "Please wait ...")
      waitmove
      get_angles
      posinit = A[monomotor]
      BEAMCHK_FLAG = 0
      count monotime
      i0 = iinit = S[monomon]
#p "\nInitial: "posinit,i0
      for (phase = 0; phase < 3 && !BEAMCHK_FLAG; ) {
         fprintf("tty", ".")
         if (fabs(A[monomotor] - posinit) > MONOTUNE["dmthmax"]) {
            print "Tuning aborted.\n"
            MONOTUNE["last"] = time()
            return(1)
         }
         A[monomotor] += monostep
         move_em
         move_poll
         sleep(.1)
         get_angles
         fprintf("tty", ".")
         count monotime
#p ">> "A[monomotor],S[monomon]
         if (S[monomon] < i0) {
            monostep *= -1
            if (phase == 1) phase++
         } else {
            if (phase == 0 || phase == 2) phase++
         }
         i0 = S[monomon]
      }
      if (BEAMCHK_FLAG) {
         print " Beam lost!. Starting again."
      } else {
         print (i0 > iinit)? " Ok!":" Mmmm?"
         comment "Monochromator retuned %g deg. Intensity increase: %.4g%%" \
                 A[monomotor]-posinit,100*(i0-iinit)/iinit
         print
         return(1)
      }
   }
'

#%MACROS%
#%IMACROS%
#
#%AUTHOR% P.Fajardo, (Original 4/95).
#  $Revision: 3.4 $ / $Date: 2008/08/12 14:23:57 $
#%TOC%