esrf

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

#%TITLE% MINIDIFF.MAC
#%NAME% %B%minidiff.mac%B% - Macros to controll the mini diffractometer
#%DESCRIPTION%
# Set of macros to control different eqipment of the MD2M diffractometer.
#%CATEGORY% MX
#%END%

global MINIDIFF[]
global MINIDIFF_CENTERING_POS[]
global MINIDIFF_HO_NAME
global MINIDIFF_SETUP
global AUTO_CENTRING_FLAG
global ENABLE_AUTO_LOOP_CENTRING
global ENABLE_AUTO_CRYSTAL_CENTRING
global ENABLE_PLAYBACK_CENTRING

def minidiff_setup '{
  unglobal MINIDIFF
  global MINIDIFF[]
  unglobal MINIDIFF_CENTERING_POS
  global MINIDIFF_CENTERING_POS[]
  local _OBJ_MINIDIFF[] tmp[]
  global MINIDIFF_PCONST
  global MINIDIFF_TCONST


  if ($# < 2) {
    print "Usage : minidiff_setup <minidiff Hardware Object> <phi pos. at ref>\nexample: minidiff_setup /minidiff 235"
    exit
  }
 
  MINIDIFF_HO_NAME = "$1"
  MINIDIFF_SETUP = 0
  MINIDIFF_TCONST=40
  MINIDIFF_PCONST=0.005

  xml_readRoles(MINIDIFF_HO_NAME)
  tmp = asso_keys(XML_tmp) 
  for (role in tmp) {
    MINIDIFF[role]["ho"]=XML_tmp[role]["hwrid"]
  }

  camera_ho = XML_tmp["camera"]["hwrid"]
  if ((xml_read(camera_ho, "/device/taconame") > -1)||(xml_read(camera_ho, "/device/tangoname") > -1)) {
    MINIDIFF["camera"]=XML_tmp[0]["__value__"]
    if (xml_read(camera_ho, "/device/tangoname")>-1) {
      # add tango device, if any (for take_backgrounds)
      MINIDIFF["tango_camera"]=XML_tmp[0]["__value__"]
    } else {
      MINIDIFF["tango_camera"]=""
    }
  } else {
    print "Could not find Falcon Device Server for Minidiff"
    exit
  }
   
  _OBJ_MINIDIFF = xml_readMotorsByRoles(MINIDIFF_HO_NAME)

  if (("focus" in _OBJ_MINIDIFF) && ("phi" in _OBJ_MINIDIFF) \
      && ("phiy" in _OBJ_MINIDIFF) && ("phiz" in _OBJ_MINIDIFF) \
      && ("sampx" in _OBJ_MINIDIFF) && ("sampy" in _OBJ_MINIDIFF) \
      && ("bstopz" in _OBJ_MINIDIFF) && ("zoom" in _OBJ_MINIDIFF) \
      && ("light" in _OBJ_MINIDIFF)) {
    ass_copy(_OBJ_MINIDIFF, MINIDIFF)
    MINIDIFF["phi"]["reference"] = $2
    if (getMinidiffCenteringPositions() < 0) {
      print "Minidiff: could not get centring positions => will not move to centring position."
    } else {
      print "Minidiff successfully configured."
    }
    MINIDIFF_SETUP=1
  } else {
    print "Could not retrieve motors from Minidiff Hardware Object : " "$1"
    exit
  }

  if (whatis("backgrounds_local_prepare") == 0)
    eval("def backgrounds_local_prepare()\'{ }\'")

  if (whatis("backgrounds_local_finish") == 0)
    eval("def backgrounds_local_finish()\'{ }\'")

}'


cdef("collection_local_prepare", "minidiff_prepare\n", "minidiff")

def _remove_safety_bath '{
  local t0

  wwrite safetyin 0

  t0 = time()
  while (wago_readch("safetyback") == 0) {
    if ((time() - t0) > 3) {
      print "Cannot move virus bath out !"
      exit
    }
  }
}'


def lightin '{
  local waittime 

  if (wago_readch("cndout") == 1) {
    # should wait
    waittime=2
  } else {
    waittime=0
  }
  wago_writech("lightin",1) 
  sleep(waittime)
}'

def lightout '{ 
  local t0

  wago_writech("lightin",0)

  t0 = time()
  while (wago_readch("cndout") == 0) {
    if ((time() - t0) > 3) {
      print "Cannot move light out !"
      exit
    }
  }
}'

def  _backlightstate() '{
local st
  st = wago_readch("cndout")
  if (st == 0) {
    return("IN")
  } else if (st == 1) {
    return("OUT")
  } else {
    return "unknown"
  }
}'

def _flightstate() '{
local st

  st = wago_readch("light2off")

  if (st == 0) {
    return("ON")
  } else if (st == 1) {
    return("OFF")
  } else {
    return "unknown"
  }
}'

def fldetin '{ wago_writech("fldin",1) }'
def fldetout '{ wago_writech("fldin",0) }'
def cryoin '{ wago_writech("SCcryoctrl",0); wago_writech("cryoin",1) }'
def cryout '{ wago_writech("cryoin",0) }'
def lighton  '{ wwrite light1off 0 }'
def lightoff '{ wwrite light1off 1 }'
def light2on '{ wwrite light2off 0 }'
def light2off '{ wwrite light2off 1 }'
def light2_is_on() '{ return 1-wago_readch("light2off") }'

def flighton() '{

  light2on
  if (FLIGHT_ON == 0)
    FLIGHT_ON = WAGODAC_VAL["flight"]
  A[flight] = FLIGHT_ON
  move_all; waitmove; getangles
}'
  
def flightoff() '{
global FLIGHT_ON

  getangles
  FLIGHT_ON = A[flight]
  light2off
  mv flight 0
}'

def annealon  '{ wago_writech("anneal",1); while (wago_readch("annealin")==0) { sleep(0.01) } }'
def annealoff '{ wago_writech("anneal",0); while (wago_readch("annealin")==1) { sleep(0.01) }; cryoin }'


def anneal '{
local anneal_time, hutch_status[]
local backwasout
local backst scintst flightst

  if ($# != 1) {
     print "Usage:  anneal time(s)"
     exit
  }

  anneal_time = $1
  backst = _backlightstate()
  flightst = _flightstate()
  backwasout = is_backstop_out()

  lightout
  backout
  fldetout
  cryout
  flighton()

  sleep(0.1)
  cdef("cleanup_once","annealoff\n","__anneal__")

  annealon

  sleep(anneal_time)

  annealoff
    
  sleep(0.1)

  cryoin

  #  one improvement would be to check the hutch status and only
  #  put the backstop in if the search has been done.

  if (backwasout == 0)
    backin

  if (backst == "IN")
    lightin
  if (flightst == "OFF")
    flightoff()
}'


def minidiff_prepare '{
    local i0gain

    lightout
    fldetout
    msclose

    # Find gain on i0. apply it to i1
    # need so that diagnostics with musst read proper values
    #wcadj i0
    #i0gain = wcreadgain(i0)
    #wcgain i1 i0gain
}'


def phi_init '{
  local mot_par[] PHI_MOTNUM PHI_AT_REF PHIDEV

  PHI_MOTNUM=motor_num(MINIDIFF["phi"])
  PHI_AT_REF=MINIDIFF["phi"]["reference"]
  PHIDEV=motor_par(PHI_MOTNUM, "device_id")

  SCMinidiffGetControl
 
  printf("PHI INIT:\n  - Setting phi velocity and acceleration\n")
  mot_par[0] = motor_par(PHI_MOTNUM,"config_velocity")
  mot_par[1] = motor_par(PHI_MOTNUM,"config_acceleration")
  chg_dial(PHI_MOTNUM,0)
  chg_offset(PHI_MOTNUM,0)
  esrf_io(PHIDEV, "AxisWrCmdSync",sprintf("SP %d",mot_par[0]))
  esrf_io(PHIDEV, "AxisWrCmdSync",sprintf("AC %d",mot_par[0]/mot_par[1]*1000))

  printf("  - Resetting GALIL controller\n")
  esrf_io(PHIDEV, "AxisWrCmdSync", "OE0")
  esrf_io(PHIDEV, "AxisWrCmdSync", "SHA")
  sleep(3)
  printf("  - Now searching for HOME signal\n    ")
  esrf_io(PHIDEV, "AxisWrCmdSync", "FIA")
  esrf_io(PHIDEV, "AxisWrCmdSync", "BGA")

  while(esrf_io(PHIDEV, "AxisWrCmdSync", "TSA") & 0x80) {
     printf(".");sleep(0.5)
  }
  printf ("\n")
  
  if (esrf_io(PHIDEV, "AxisWrCmdSync", "TI") == 15) {
     printf("  - Setting positions to zero ")
     get_angles
     A[PHI_MOTNUM] = PHI_AT_REF
     move_em; move_poll; get_angles
     chg_dial(PHI_MOTNUM,0)
     chg_offset(PHI_MOTNUM,0)
     tty_cntl("md")
     printf("Ok: done\n")
     tty_cntl("me")
  } else {
     tty_cntl("md")
     printf("Error!\n")
     tty_cntl("me")
  }

  esrf_io(PHIDEV, "AxisWrCmdSync", "OE1")
}'


def zoom_init '{
  printf("ZOOM INIT:\n  - Adjusting zoom motor\n")
  set_lm zoom  300 -300
  printf("  - Searching for reference signal\n")
  chg_dial( zoom, "lim-" )
  set_dial zoom 102
  set zoom 102
  printf("  - Moving zoom to 50%\n")
  mv zoom 50 
  set_lm zoom 0 100
  
  tty_cntl("md")
  printf("Ok: done\n")
  tty_cntl("me") 

  mv zoom 0
}'


def autofocus '{
    local negativeStep, n_contrast
    local positiveStep, p_contrast
    local old_contrast, phix_pos

    negativeStep = -0.1
    positiveStep = 0.1

    while ((negativeStep <= -0.015) || (positiveStep >= 0.005)) {
      mvr phix positiveStep

      p_contrast = esrf_io(MINIDIFF["camera"], "DevCcdGetTGradient", 15000)

      phix_pos = negativeStep - positiveStep
      mvr phix phix_pos

      n_contrast = esrf_io(MINIDIFF["camera"], "DevCcdGetTGradient", 15000) 

      if ((p_contrast > old_contrast) && (p_contrast > n_contrast)) {
         phix_pos = positiveStep - negativeStep 
         mvr phix phix_pos 
         positiveStep = positiveStep * 0.75
         negativeStep = negativeStep * 0.33
         old_contrast = p_contrast
      } else if ((n_contrast > old_contrast) && (n_contrast > p_contrast)) {
         positiveStep = positiveStep * 0.33
         negativeStep = negativeStep * 0.75
         old_contrast = n_contrast
      } else {
         mvr phix -negativeStep
         positiveStep = positiveStep * 0.5
         negativeStep = negativeStep * 0.5
      }
   }
}'


def minidiff_init '{ 
  # does minidiff reset : move motors to switches,
  # and set default position from Minidiff XML file
  local query queryResult[] motrole motmne motnum position
  local i k m tmp tmp0[] REFERENCE_POS[] scdisabled

  scdisabled = wago_readch("SCdisable")

  if (scdisabled == 0) {
    SCInUse 0
  }

  printf("MINIDIFF INIT:\n")
 
  query = sprintf("xml_read(\"%s\", \"/equipment/resetPosition/*\")", MINIDIFF_HO_NAME)
  queryResult = prop_get(HWR_dev, query)

  if (!("__error__" in queryResult)) {
    tmp0 = asso_keys(queryResult)
    for (k in tmp0) {
      i = split(queryResult[k]["__path__"], tmp, "/")
      motrole = substr(tmp[i-1], 0, length(tmp[i-1])-3)
      position = queryResult[k]["__value__"]
      
      REFERENCE_POS[motrole]=position
    }
  } else {
    printf("Error: could not retrieve reset pos. from Mindiff Hardware Object\n")
    exit
  }

  get_angles

  for (motrole in REFERENCE_POS) {
    if (($# == 0)||(motrole=="$1")) { 

    motmne = MINIDIFF[motrole]
    motnum = motor_num(motmne)
    cntrl = motor_par(motnum,"controller")
    if (motnum >= 0) {
      tstart = time()
      tcurr = time()
      read_motors(0)
      pstart = A[motnum]
      
      motsign = motor_par(motnum, "step_size") > 0 ? 1: -1
      if ((pstart-(motsign*0.1))<get_lim(motnum, -1)) {
        dest=get_lim(motnum, -1)
      } else {
        dest=pstart-(motsign*0.1)
      }
      printf("  - mvr %s %f\n", motmne, dest-pstart)
      A[motnum]=dest
      move_em; move_poll

      printf("  - searching lim- for motor %s  ", motmne)
      chg_dial(motnum, "lim-")
      sleep(0.5)

      while(wait(0x21)){
        if (cntrl == "MAXE_E") {
          read_motors(0)
          if (fabs(A[motnum] - pstart) < MINIDIFF_PCONST) {
              print "motor is at " A[motnum] " and was at " pstart
              eprintf ("Motor %s is not moving, exiting...\n", motmne)
              stop(1)
              exit
          } else {
            pstart=A[motnum]  
          }
        } else {
          if ((time() - tstart) > MINIDIFF_TCONST) {
            eprintf("Timeout while searching limit switch for motor %s,", motmne)
            eprintf (" exiting...\n")
            stop(1)
            exit
          }
        }
        printf("\b%s", substr("-\\|/", (m=++m%4)+1, 1))
        sleep(0.5)
      }
      printf("\b\n")

      printf("  - setting reference pos. to %g\n", REFERENCE_POS[motrole])
      chg_dial(motnum,REFERENCE_POS[motrole])
      chg_offset(motnum, REFERENCE_POS[motrole])

      motsign = motor_par(motnum, "step_size") > 0 ? 1: -1

      printf("  - moving back motor from limit\n")
      get_angles
      A[motnum] = A[motnum] + (motsign*2)
      move_em; move_poll
    } else {
      printf("Invalid motor %s, exiting", motmne)
      exit
    }
  }}

  if ($# == 0) {
     if (KAPPA_IN_USE)
       minikappa_init
     else
       phi_init
  }

  #SCInUse 1-scdisabled
  SCInUse 1
}'


def getMinidiffCenteringPositions() '{
  local k, i, motrole, query, queryResult[], position, delta, tmp0[], tmp[]
  
  unglobal MINIDIFF_CENTERING_POS
  global MINIDIFF_CENTERING_POS[]

  query = sprintf("xml_read(\"%s\", \"/equipment/autoCentering/referencePosition/*\")", MINIDIFF_HO_NAME)
  queryResult = prop_get(HWR_dev, query)

  if (!("__error__" in queryResult)) {
    tmp0 = asso_keys(queryResult)
    for (k in tmp0) {
      i = split(queryResult[k]["__path__"], tmp, "/")
      motrole = substr(tmp[i-1], 0, length(tmp[i-1])-3)
      position = queryResult[k]["__value__"]
      delta = queryResult[k]["delta"]
      MINIDIFF_CENTERING_POS[motrole]["delta"]=delta
      MINIDIFF_CENTERING_POS[motrole]=position 
    }
    
    return (1)
  } else {
    print queryResult["__error__"]
    return(-1)
  }
}' 


def minidiff_prepare_centring '{
  local tmp[] tmp2[] motrole motmne motnum delta position

  print "moving minidiff to centring position..."

  tmp = asso_keys(MINIDIFF_CENTERING_POS)

  getangles  

  for (motrole in tmp) {
    motmne = MINIDIFF[motrole]
    printf("  - moving %s to %f\n", motmne, MINIDIFF_CENTERING_POS[motrole])
    motnum = motor_num(motmne)
    A[motnum]=MINIDIFF_CENTERING_POS[motrole]
  } 

  if (($# > 0)&&(length("$1")>0)) {
    print "moving minidiff to crystal last centered pos."
    tmp2 = _minidiff_split("$1")

    for (motrole in tmp2) {
      motmne = MINIDIFF[motrole]
      printf("  - moving %s to %f\n", motmne, tmp2[motrole])
      motnum = motor_num(motmne)
      A[motnum]=tmp2[motrole]
    }
  }

  move_em

  while (wago_readch("SCparked")==0) {
    sleep(1)
  }
  
  lightin

  move_poll

  ZOOM_LIGHT["old_zoom_pos"]=-1

  AUTO_CENTRING_FLAG=AUTO_CENTRING_FLAG+1
}'

def minidiff_prepare_autocentring '{
  mv flight 0

  AUTO_CENTRING_FLAG=-1
  minidiff_prepare_centring
}'

def _minidiff_split(s) '{
  local tmp[] tmp2[] tmp3[]
  split(s, tmp, ";")
  for (i in tmp) {
    split(tmp[i], tmp2, " ")
    tmp3[tmp2[0]]=tmp2[1]
  }
  return tmp3
}'


def minidiff_take_periodic_backgrounds '{
  local directory filename bkg_mtime 

  # find where backgrounds are stored
  if (xml_read(MINIDIFF_HO_NAME, "/equipment/autoCentering/imagesFolder") >= 0) {
    directory = XML_tmp[0]["__value__"]
    filename = sprintf("%s/background1.tif", directory)
        
    # now check background 1 file last modification time
    bkg_mtime = file_info(filename, "mtime")
    if ((time() - bkg_mtime) > (1*3600)) {
      minidiff_take_backgrounds
    } 
    else {
      print "Backgrounds are recent. Nothing to do."
    }
  }
}'

def _minidiff_take_zoom_backgrounds '{
  # move to zoom levels, and take images
  getangles
  ZOOM_LIGHT["old_zoom_pos"]=-1
  zoom_mot = motor_num(ZOOM_LIGHT["zoom_motor"])
  if (zoom_mot < 0) {
    print "ABORTING: could not retrieve zoom motor !"
    egui_logmsg("ABORTING: could not retrieve zoom motor (check zoomlight macro setup)")
  } else {
    len=0
    for (k in ZOOM_LIGHT[zoom_mot]) {
      len+=1
    }

    for (i=0; i<len;i+=1) {
      pos = i*20
      egui_logmsg(sprintf("  - moving to zoom level %d (%d)", i+1, pos))
      A[zoom_mot]=pos
      move_em; move_poll

      # take image
      egui_logmsg(sprintf("  - taking background image %d : %s/background%d_%d.tif", i+1, directory, MINIDIFF["aperture_index"], i+1))
      if (MINIDIFF["tango_camera"]!="") {
          local idx
          idx = MINIDIFF["aperture_index"]
          unix_cmd=sprintf("python -c %s", sprintf("\'import PyTango; import Image; dev=PyTango.DeviceProxy(\"%s\"); w=dev.read_attribute(\"Width\").value; h=dev.read_attribute(\"Height\").value;img=dev.read_attribute(\"Image\").value\ntry: im=Image.frombuffer(\"RGB\", (w,h), img)\nexcept: im=Image.frombuffer(\"RGB\", (w,h), dev.read_attribute(\"RgbImage\").value)\nim=im.transpose(Image.FLIP_TOP_BOTTOM)\nim.save(\"%s/background%d_%d.tif\")\'", MINIDIFF["tango_camera"],directory,idx,i+1)) 
      } else {
        local idx
        idx = MINIDIFF["aperture_index"]
        unix_cmd=sprintf("python -c %s", sprintf("\'import TacoDevice; import Image; dev=TacoDevice.TacoDevice(\"%s\"); dev.tcp(); data=dev.DevCcdRead(1); img=Image.frombuffer(\"RGB\", (dev.DevCcdXSize(), dev.DevCcdYSize()), data); pixmap=img.tostring(\"raw\", \"BGR\"); img=Image.frombuffer(\"RGB\", img.size, pixmap);img.save(\"%s/background%d_%d.tif\")\'", MINIDIFF["camera"], directory, idx, i+1))
      }
      #print unix_cmd
      unix(unix_cmd)
    }
    egui_logmsg("Done !")
  }
}'

if (whatis("multiaperture_diameter")==0) {
  eval("def multiaperture_diameter() '\{\}'")
}

def minidiff_take_backgrounds '{
  local directory filename bkg_mtime k len i pos
 
  # find where backgrounds are stored
  if (xml_read(MINIDIFF_HO_NAME, "/equipment/autoCentering/imagesFolder") >= 0) {
    directory = XML_tmp[0]["__value__"]
        
      print "taking backgrounds for Automatic Centring... please wait"
      egui_logmsg("Taking backgrounds for Automatic Centring... please wait")
      
      lightin
      backout
  
      backgrounds_local_prepare()
  
      if (AP_XML == 0) {
        MINIDIFF["aperture_index"] = 0
        _minidiff_take_zoom_backgrounds   
      } else {
        for (diameter in AP_IDX) {
          multiaperture_diameter(diameter)
 
          MINIDIFF["aperture_index"] = AP_IDX[diameter]       
 
          _minidiff_take_zoom_backgrounds
        } 
      }
    backgrounds_local_finish()
  } else {
    printf("Could not retrieve autocentring information from minidiff XML file\n")
  }
}'

#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% BLISS%BR%
#$Revision: 1.53 $$Date: 2012/09/06 16:17:16 $
#%END%
#%LOG%
#$Log: minidiff.mac,v $
#Revision 1.53  2012/09/06 16:17:16  guijarro
#workaround spec interpreter bug with continue keyword
#
#Revision 1.52  2011/05/30 17:32:16  guijarro
#define multiaperture_diameter function if necessary (spec is weird!)
#
#Revision 1.51  2011/05/30 11:40:54  guijarro
#added [] when missing on local associative array declaration
#
#Revision 1.50  2011/04/19 14:26:35  guijarro
#take backgrounds for each aperture
#
#Revision 1.49  2011/02/18 12:29:00  beteva
#added backgrounds_local actions. Changed the safety to virus bath.
#
#Revision 1.48  2010/11/16 12:53:48  guijarro
#do not move light in in minidiff_prepare_centring if SC arm is not parked
#
#Revision 1.47  2010/11/16 11:02:49  guijarro
#call minikappa_init instead of phi_init if kappa i sused
#
#Revision 1.46  2010/11/16 10:26:20  guijarro
#perform a small movement of all the motors involved in the minidiff_init macro at the start of the macro
#
#Revision 1.45  2010/11/02 15:55:11  beteva
#changed the IN/OUT state of the front light, added change of the
#flight motor when flighton/off
#
#Revision 1.44  2010/10/28 11:45:09  beteva
#restore the lights (back and front) and the backstop at the end
#of the anneal procedure
#