esrf

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

#%TITLE% MICRODIFF.MAC
#%NAME% MICRODIFF.MAC - Macros to controll the micro diffractometer
#%DESCRIPTION%
# The macros give access to the fast shutter and the oscillation scan
# of the micro diffractometer MD2 via a TANGO device server.
# The setup needs the name of the TANGO device as parameter to
# open the access for the macros to the device server and the oscilation
# motor mnemonic.
#%END%

#%UU% [device_name oscil_motor_name]
#%MDESC% Declare the micro diffractometer device to be used by the macros.
def microdiff_setup '{
global MICRODIFF_DEVICE OSCIL_MOTOR_NAME OSCIL_MOTOR_NUM
global MICRODIFF_DEBUG
global MICRODIFF[] MICRODIFF_HO
local mdtype

  if ($# != 3) {
    MICRODIFF_DEVICE = getval("Microdiff tango device name:", MICRODIFF_DEVICE)
    OSCIL_MOTOR_NAME = getval("Oscillation motor name:", OSCIL_MOTOR_NAME) 
    MICRODIFF_HO = getval("Microdiff hardware object:", MICRODIFF_HO)
  } else {
    MICRODIFF_DEVICE = "$1"
    OSCIL_MOTOR_NAME = "$2"
    MICRODIFF_HO = "$3"
  }

  if (split(MICRODIFF_DEVICE, mdtype,":") > 1)
    MICRODIFF["mdtype"] = 1

  local tmp camera_ho
  xml_readRoles(MICRODIFF_HO)
  tmp = asso_keys(XML_tmp)
  for (role in tmp) {
    MICRODIFF[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)) {
    MICRODIFF["camera"]=XML_tmp[0]["__value__"]
    if (xml_read(camera_ho, "/device/tangoname")>-1) {
      # add tango device, if any (for take_backgrounds)
      MICRODIFF["tango_camera"]=XML_tmp[0]["__value__"]
    } else {
      MICRODIFF["tango_camera"]=""
    }
  } else {
    printf("Could not find Camera Device Server for Microdiff\n")
    exit
  }


  OSCIL_MOTOR_NUM = motor_num(OSCIL_MOTOR_NAME)
  if (OSCIL_MOTOR_NUM  == -1) {
    tty_cntl("md")
    eprintf("Invalif oscilation motor %s, check the spec config!\n", \
	OSCIL_MOTOR_NAME)
    tty_cntl("me")
    return
  }

  #need longer timeout for commands like Reset
  tango_io (MICRODIFF_DEVICE, "timeout", 60)
  if (TANGO_ERR) {
    tty_cntl("md")
    eprintf ("MD2: Device server not running, exiting...")
    tty_cntl("me")
    print_tango_err()
    return
  }
  cdef("prompt_mac", "microdiff_prompt\n","_microdiff_")

  cdef("local_get_beamsize", "microdiff_get_beamsize()\n", "_microdiff_")
  cdef("local_abort_scan", "microdiff_abort_scan()", "_microdiff_")
}'

def microdiff_get_calibration() '{ return 1 }'

def microdiff_get_beamsize() '{
  global APERTURE_COEF

  MXSPEC_PARS["beamsize"]["x"] = microdiff_aperture_diameter(0) / 1000.0
  MXSPEC_PARS["beamsize"]["y"] = MXSPEC_PARS["beamsize"]["x"]
  
  if (MXSPEC_PARS["beamsize"]["y"] > MXSPEC_PARS["beamsize"]["max_ver"]) {
    MXSPEC_PARS["beamsize"]["y"]=MXSPEC_PARS["beamsize"]["max_ver"]
  }
  APERTURE_COEF = microdiff_get_calibration()
}'


#%UU%
#%MDESC% Clean-up all hooks for the set of macros
def microdiff_unsetup '{
  cdef("" ,"" ,"_microdiff_", "delete")
}'

#%IU%
#%MDESC% Delete the hook created for the cleanup
def microdiff_prompt '{
   cdef("" ,"" ,"microdiff_cleanup", "delete")
}'

def microdiff_init '{

  msclose
  printf("Initialising the microdiff. May take several minutes. Please wait\n")
  #first bring all the equipment under the cover
  microdiff_cover()

  #wait for movement to be finished
  wait_ready()

  if (MICRODIFF["mdtype"])
    tango_io(MICRODIFF_DEVICE,"startHomingAll")
  else
    tango_io(MICRODIFF_DEVICE,"StartHomingAll")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error initializing microdiff.")
  } else {
    wait_ready()
  }
  zoom_init()
  kappa_init
}'

def phi_init '{

  msclose
  printf("Initialising phi. May take several minutes. Please wait\n")

  if (MICRODIFF["mdtype"])
    tango_io(MICRODIFF_DEVICE,"startHomingMotor","Omega")
  else
    tango_io(MICRODIFF_DEVICE,"StartHomingOmega")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error homing phi.")
  } else {
    wait_ready()
  }

}'

def zoom_init() '{

  if (MICRODIFF["mdtype"])
    tango_io(MICRODIFF_DEVICE,"startHomingMotor","Zoom")
  else
    tango_io(MICRODIFF_DEVICE,"StartHomingZoom")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error homing zoom.")
  } else {
    wait_ready()
  }
  mv zoom 1
}'
#-------- fast shutter --------
#%IU% ()
#%MDESC% Return the fast shutter position.
def _msstate()  '{
local st

  st = tango_get(MICRODIFF_DEVICE, "FastShutterIsOpen")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the fast shutter.")
    return("unknown")
  }
  if (st == 1)
    st = "OPEN"
  else if (st == 0)
    st = "CLOSED"
  else
    st = "unknown"
  return(st)
}'

#%IU% ()
#%MDESC% Open the fast shutter
def microdiff_msopen() '{
global FAST_SHUTTER_STATE

  if (wait_ready() == -1) {
    egui_fatal("MD2: error opening the fast shutter.")
    return("unknown")
  }

  if (MICRODIFF["mdtype"])
    tango_put(MICRODIFF_DEVICE, "FastShutterIsOpen",1)
  else
    tango_io(MICRODIFF_DEVICE, "OpenFastShutter")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error opening the fast_shutter.")
  } else {
    FAST_SHUTTER_STATE = _msstate()
    if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Fast shutter %s",  FAST_SHUTTER_STATE))
  }
}'

#%IU% ()
#%MDESC% Close the fast shutter
def microdiff_msclose() '{
global FAST_SHUTTER_STATE

  if (wait_ready() == -1) {
    egui_fatal("MD2: error closing the fast shutter.")
    return("unknown")
  }

  if (MICRODIFF["mdtype"])
    tango_put(MICRODIFF_DEVICE, "FastShutterIsOpen",0)
  else
    tango_io(MICRODIFF_DEVICE, "CloseFastShutter")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error closingthe  fast_shutter")
  } else {
    FAST_SHUTTER_STATE = _msstate()
    if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Fast shutter %s",  FAST_SHUTTER_STATE))
  }
}'

#%UU%
#%MDESC% Open the fast shutter.
def msopen '{
global FAST_SHUTTER_STATE

  FAST_SHUTTER_STATE = "moving"
  microdiff_msopen()
}'

#%UU%
#%MDESC% Close the fast shutter.
def msclose '{
global FAST_SHUTTER_STATE

  FAST_SHUTTER_STATE = "moving"
  microdiff_msclose()
}'
#-------- fast shutter end --------

#-------- beam stop --------
#%IU% (pos)
#%MDESC% Move BeamStop to %B%pos%B% on beam (pos=1), out of the beam (pos=2).
def microdiff_beamstop(pos) '{
local msg stat lpos

  stat = _bsstate()
  if ((stat == "IN") && (pos == 1))
    return(0)

  if ((stat == "OUT") && (pos == 2))
    return(0)

  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the backstop.")
    return(-1)
  }

  if (MICRODIFF["mdtype"]) {
    if (pos == 1)
      lpos = "BEAM"
    else if (pos == 2)
      lpos = "OFF"
    else
      lpos = "PARK"
    tango_put(MICRODIFF_DEVICE, "CapillaryPosition",lpos)
  } else
    tango_put(MICRODIFF_DEVICE, "CapillaryBSPredefinedPosition",pos)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving beamstop")
    return(-1)
  }
  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the beamstop.")
    return(-1)
  }
  return(0)
}'

#%IU% ()
#%MDESC% Return the position of the BeamStop.
def _bsstate() '{
local st

  if (MICRODIFF["mdtype"])
    st = tango_get(MICRODIFF_DEVICE, "CapillaryPosition")
  else
    st = tango_get(MICRODIFF_DEVICE, "CapillaryBSPredefinedPosition")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the beam stop.")
    return("unknown")
  }
  if ((st == 1) || (st == "BEAM"))
    st="IN"
  else if ((st == 2) || (st == "OFF"))
    st="OUT"
  else
    st="unknown"
 
  return(st)
}'

#%IU% ()
#%MDESC% Move BeamStop ON the beam.
def microdiff_bson() '{
local msg

  if (microdiff_beamstop(1) == -1)
    egui_fatal("MD2: cannot move beamstop in")
  else {
    #wait until movement finished
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move beamstop in")
    } else {
      msg = _bsstate()
      if (MICRODIFF_DEBUG)
        egui_logmsg(sprintf ("Backstop %s", msg))
    }
  }
}'

#%IU% ()
#%MDESC% Move BeamStop OFF beam
def microdiff_bsoff() '{
local msg

  if (microdiff_beamstop(2) == -1)
    egui_fatal("MD2: cannot move beamstop in")
  else {
    #wait until movement finished
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move beamstop in")
    } else {
      msg = _bsstate()
      if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Backstop %s", msg))
    }
  }
}'

#%UU%
#%MDESC% Move BeamStop ON beam
def backin '{
  microdiff_bson()
}'

#%UU%
#%MDESC% Move BeamStop OFF beam
def backout '{
  microdiff_bsoff()
}'
#-------- beam stop end --------

#-------- fluo detector --------
#%IU% (pos)
#%MDESC%  Move the fluo detector in (pos = 0) or out (pos = 1).
def microdiff_fldet(pos) '{
local ret

  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the fluo detector.")
    return(-1)
  }

  if (microdiff_phase(4) < 0)
    return(-1)

  tango_put(MICRODIFF_DEVICE,"FluoDetectorIsBack", pos)
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the fluo detector.")
    return(-1)
  }
  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the fluo detector.")
    return(-1)
  }
  return(0)
}'

#%IU% ()
#%MDESC% Return the fluorescen detector position.
def _flstate() '{
local st

  st = tango_get(MICRODIFF_DEVICE,"FluoDetectorIsBack")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the fluo detector.")
    return("unknown")
  }
  if (st == 0)
    st = "IN"
  else if (st == 1)
    st = "OUT"
  else
    st = "unknown"
  return(st)
}'

#%IU% ()
#%MDESC% Insert the fluorescent detector.
def microdiff_fldetin() '{
local msg

  if (microdiff_fldet(0) == 0) {
    msg = _flstate()
    if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Fluo detector %s", msg))
  }
}'
#%IU% ()
#%MDESC% Extract the fluorescent detector.
def microdiff_fldetout() '{
  if (microdiff_fldet(1) == 0) {
    msg = _flstate()
    if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Fluo detector %s", msg))
  }
}'

#%UU% 
#%MDESC% Insert the fluorescent detector.
def fldetin '{
  microdiff_fldetin()
  if (ismacro("local_detector_actions")) {
    local_detector_actions 1
  }
}'

#%UU%
#%MDESC% Extract the fluorescent detector.
def fldetout '{
  microdiff_fldetout()
  if (ismacro("local_detector_actions")) {
    local_detector_actions 0
  }
}'
#-------- fluo detector end --------

#-------- cryostream --------
#%IU% (pos)
#%MDESC%  Move the cryo in (pos = 0) or out (pos = 1).
def microdiff_cryo(pos) '{

  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the cryostream.")
    return(-1)
  }
  tango_put(MICRODIFF_DEVICE,"CryoIsBack", pos)
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the cryostream.")
    return
  }
  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the cryostream.")
    return(-1)
  }
}'

#%IU% ()
#%MDESC% Return the cryostream position.
def _cryostate() '{
local st

  st = tango_get(MICRODIFF_DEVICE,"CryoIsBack")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the cryostream.")
    return("unknown")
  }
  if (st == 0)
    st = "IN"
  else if (st == 1)
    st = "OUT"
  else
    st = "unknown"
  return(st)
}'

#%IU% ()
#%MDESC% Insert the cryostream.
def microdiff_cryoin() '{
local msg

  if (microdiff_cryo(0) == 0) {
    msg = _cryostate()
    if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Cryostream %s", msg))
  }
}'

#%IU% ()
#%MDESC% Extract the cryostream.
def microdiff_cryout() '{
local msg

  if (microdiff_cryo(1) == 0) {
    msg = _cryostate()
    if (MICRODIFF_DEBUG)
      egui_logmsg(sprintf ("Cryostream %s", msg))
  }
}'

#%UU%
#%MDESC% Insert the cryostream.
def cryoin '{
  microdiff_cryoin()
}'

#%UU%
#%MDESC% Extract the cryostream.
def cryout '{
  microdiff_cryout()
}'
#-------- cryostream end --------

#-------- back light --------
#%IU% (pos)
#%MDESC%  Move the backlight in (pos = 1) or out (pos = 0).
def microdiff_light(pos) '{
local st t0

  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the light.")
    return(-1)
  }

  st = _backlightstate()
  if ((st == "IN") && (pos==1))
    return;
  if ((st == "OUT") && (pos==0))
    return;

  tango_put(MICRODIFF_DEVICE,"BackLightIsOn", pos)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the backlight.")
    return(-1)
  }
  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the back light.")
    return(-1)
  }
  sleep(1)  
}'

#%IU% ()
#%MDESC% return the backlight position
def _backlightstate() '{
local st

  st = tango_get(MICRODIFF_DEVICE,"BackLightIsOn")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the back light.")
    return("unknown")
  }
  #st = esrf_io(sprintf("%s/BackLightIsOn",MICRODIFF_DEVICE), "DevRead")
  if (st==1) {
    return("IN")
  } else if (st==0) {
    return("OUT")
  } else {
    return "unknown"
  }

  return(st)
}'

#%IU% ()
#%MDESC% Insert the backlight.
def microdiff_lightin() '{
local msg

  if (microdiff_light(1) == 0) {
    msg =  _backlightstate()
    if (MICRODIFF_DEBUG)
      egui_logmsg (sprintf("Backlight %s", msg))
  }
}'

#%IU% ()
#%MDESC% Extract the backlight.
def microdiff_lightout() '{
local msg

  if (microdiff_light(0) == 0) {
    msg =  _backlightstate()
    if (MICRODIFF_DEBUG)
      egui_logmsg (sprintf("Backlight %s", msg))
  }
}'

#%UU%
#%MDESC% Insert the backlight.
def lightin '{
  microdiff_lightin()
}'

#%UU%
#%MDESC% Extract the backlight.
def lightout '{
  microdiff_lightout()
}'

#%IU% (value)
#%MDESC% Set the backlight factor (value = 0 to 2). Read it (value = 99).
#Return the light factor if OK, -1 if error.
def microdiff_light_factor(value) '{
local val

  if ((value < 0) || (value > 2) && (value != 99)) {
    eprintf ("Wrong value %0.3f, accepted value 0-2 or 99\n", value)
    return(-1)
  }

  TANGO_ERR = "-1"
  if (value == 99) {
    val = tango_get(MICRODIFF_DEVICE,"BackLightFactor")
    if (TANGO_ERR) {
      print_tango_err()
      egui_logmsg("MD2: cannot read the backlight factor.")
      return(-1)
    }
    return(val)
  }
  tango_put(MICRODIFF_DEVICE,"BackLightFactor", value)
  if (TANGO_ERR) {
    print_tango_err()
    egui_logmsg("MD2: cannot set the backlight factor.")
    return(-1)
  }
  return(value)
}'
#-------- back light end --------

#%IU% <disk> <directory>
#%MDESC%<disk>= windows disk (ex:\\bldata)
#%BR%<directory>= windows mapped directory (ex: opd14\inhouse\md2)
def microdiff_image_path '{
local disk directory

  if ((MICRODIFF["mdtype"]) {
    eprintf ("microdiff_image_path is deprecated, nothing done\n")
    return(0)
  }

  if ($#!=2) {
    print "$0 <disk> <directory>"
    exit
  }

  if (!_microdiff_image_path("$1", "$2"))
    eprintf("Error setting image path\n")
  else
    printf ("Image Path Set to %s\%s\n", $1, $2)
}'

#%IU% (disk, directory)
#%MDESC% Set the path to save the image.
def _microdiff_image_path(disk, directory) '{
local filepar[]

  if ((MICRODIFF["mdtype"]) {
    eprintf ("_microdiff_image_path() is deprecated, nothing done\n")
    return(0)
  }

  filepar[0]= disk
  filepar[1]= directory
  tango_io(MICRODIFF_DEVICE, "SetCapturedImagePath", filepar)
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error sending SetCapturedImagePath.")
    return (0)
  }
  return (-1)
}'

#%IU% ()
#%MDESC% Abort the scan.
def microdiff_abort_scan() '{

  HELICAL_SCAN4D = 0
  HELICAL_SCAN4D_MANUAL = 0

  if (MICRODIFF["mdtype"])
    tango_io (MICRODIFF_DEVICE, "abort")
  else
    tango_io (MICRODIFF_DEVICE, "AbortScan")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: cannot abort scan!")
    return(-1)
  }
  return(0)
}'

#%IU%
#%MDESC% Called from the cleanup (by typing Ctrl-C). Stops properly
# the scan.
def microdiff_cleanup '{
global MICRODIFF_OSC

  if (microdiff_abort_scan() < 0) {
    egui_fatal("Cleanup not finished!")
  } else {
    wait_ready()
  }
  MICRODIFF_OSC = 0

  #Put the microdiff in centring state
  if (microdiff_phase(1) < 0) {
    egui_fatal("MD2: cannot abort scan. Cleanup not finished!")
  }
  egui_logmsg("actions aborted, cleanup finished")
}'

#%IU%
#%MDESC% hook the oscillation to the data collection macro.
def microdiff_oscil_on '{
  cdef("osc_scan","microdiff_osc_scan_m","_pxoscil",0x20)
  cdef("osc_prepare","microdiff_prepare_oscil","_pxoscil",0x20)
}'

#%IU%
#%MDESC% Remove the data collection macro hook
def microdiff_oscil_off '{
  cdef("","","_pxoscil","delete")
}'

#%IU%
#%MDESC% Dummy macro required by the prodc data collection one.
def microdiff_prepare_oscil '{
  print $*
  printf("microdiff_prepare_oscil, not used\n")
  if (HELICAL_OSCIL == 1)
    helical_follow_phi($1)
}'

#%IU%
#%MDESC% Resets all faults or alarms on the micro diffractometer
def microdiff_reset '{

  return(0)
  
  if (MICRODIFF["mdtype"])
    tango_io (MICRODIFF_DEVICE, "restart",0)
  else
    tango_io (MICRODIFF_DEVICE, "Reset")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: cannot reset the microdiff.")
  }
}'

#%IU%
#%MDESC% Move sample out of beam
def microdiff_sample_off '{
local msg

  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the sample out of beam.")
    return(-1)
  }

  if (MICRODIFF["mdtype"])
    tango_io (MICRODIFF_DEVICE, "startMoveSampleOffBeam")
  else
    tango_io (MICRODIFF_DEVICE, "MoveSampleOffBeam")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving sample out of the beam.")
  } else {
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move sample out of the beam")
    } else
      egui_logmsg("Sample moved out of beam!")
  }
}'

#%IU%
#%MDESC% Move sample in beam
def microdiff_sample_on '{

  if (wait_ready() == -1) {
    egui_fatal("MD2: error moving the sample on beam.")
    return(-1)
  }

  if (MICRODIFF["mdtype"])
    tango_io (MICRODIFF_DEVICE, "startMoveSampleOnBeam")
  else
    tango_io (MICRODIFF_DEVICE, "MoveSampleOnBeam")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving sample on beam.")
  } else {
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move sample on beam")
    } else
      egui_logmsg("Sample moved in beam!")
  }
}'


#%IU%
#%MDESC% Lock GUI
def microdiff_GUI_lock '{

  if (MICRODIFF["mdtype"])
    tango_put(MICRODIFF_DEVICE, "LocalGuiLockOut", 1)
  else
    tango_io(MICRODIFF_DEVICE, "LocalGUILockout", 1)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error locking microdiff GUI.")
  } else
    egui_logmsg("microdiff GUI locked")
}'

#%IU%
#%MDESC% Unock GUI
def microdiff_GUI_unlock '{

  if (MICRODIFF["mdtype"])
    tango_put(MICRODIFF_DEVICE, "LocalGuiLockOut", 0)
  else
    tango_io(MICRODIFF_DEVICE, "LocalGUILockout", 0)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error unlocking microdiff GUI.")
  } else
    egui_logmsg("microdiff GUI unlocked")
}'

#-------- oscillation --------
#%IU% [start_angle end_angle exposure_time nb_of_oscillations]
#%MDESC% Program the oscillation frame on the micro diffractometer.
#  The spindle oscillates the "number_of_oscillations" times between the 
# "start_angle" and the "end_angle" for the "exposure_time" seconds.
def microdiff_osc_scan_m '{

  microdiff_osc_scan($1,$2,$3,$4)
}'

#%IU% (start_angle, end_angle, exposure_time, nr_osc, flag)
#%MDESC% Program the oscillation frame from %B%start_angle%B% to
# %B%end_angle%B% for %B%exposure_time%B% seconds, %B%nr_osc%B% times.
# If %B%flag%B% = 1, do not open the fastshutter.
def microdiff_osc_scan(start_angle, end_angle, exposure_time, nr_osc, flag) '{
local t0 f s4d
global MICRODIFF_OSC
global SAVE_PARAMS

  f[0] = CURRENT_IMAGE["image_number"]
  t0 = time()
  SAVE_PARAMS["start_time"] = t0
  printf("entering microdiff_osc_scan... ");
  MICRODIFF_OSC = 0
  cdef ("cleanup_once","microdiff_cleanup\n", "_microdiff_")


  f[1] = start_angle
  f[2] = end_angle - start_angle
  f[3] = exposure_time
  f[4] = nr_osc

  if ((HELICAL_SCAN4D == 1) && \
      (MXCOLLECT_PARS["experiment_type"] == "classic")) {
    HELICAL_SCAN4D = 0
    HELICAL_OSCIL = 1
  }
  printf ("Helical oscillation: %s\n", \
	((HELICAL_SCAN4D == 1) || (HELICAL_OSCIL == 1))? "YES":"NO")

  if (flag == 1) {
    tango_put(MICRODIFF_DEVICE,"FastShutterIsEnabled", 0)
    if (TANGO_ERR) {
      print_tango_err()
      egui_fatal("MD2: errror programming the fast shutter.")
      exit
    }
  }

  if (HELICAL_SCAN4D == 1) {
    HELICAL_OSCIL = 0
    #go to start position
    #helical_getpos 11

    if (HELICAL_PARS["nb_pos"] < 2) {
      egui_fatal("Start/Final scan positions not set, aborting...")
      exit
    }
    s4d[0]= f[1]
    s4d[1]= f[2]
    s4d[2]= f[3]
    if (MICRODIFF["mdtype"]) {
      s4d[3] = HELICAL_OSCIL_POS[1]["phiy"]
      s4d[4] = HELICAL_OSCIL_POS[1]["phiz"]
      s4d[5] = HELICAL_OSCIL_POS[1]["sampx"]
      s4d[6] = HELICAL_OSCIL_POS[1]["sampy"]
      s4d[7] = HELICAL_OSCIL_POS[2]["phiy"]
      s4d[8] = HELICAL_OSCIL_POS[2]["phiz"]
      s4d[9] = HELICAL_OSCIL_POS[2]["sampx"]
      s4d[10] = HELICAL_OSCIL_POS[2]["sampy"]
    } else {
      s4d[3]= HELICAL_OSCIL_POS[1]["phix"]
      s4d[4] = HELICAL_OSCIL_POS[2]["phix"]
      s4d[5] = HELICAL_OSCIL_POS[1]["phiy"]
      s4d[6] = HELICAL_OSCIL_POS[2]["phiy"]
      s4d[7] = HELICAL_OSCIL_POS[1]["phiz"]
      s4d[8] = HELICAL_OSCIL_POS[2]["phiz"]
      s4d[9] = HELICAL_OSCIL_POS[1]["sampx"]
      s4d[10] = HELICAL_OSCIL_POS[2]["sampx"]
      s4d[11] = HELICAL_OSCIL_POS[1]["sampy"]
      s4d[12] = HELICAL_OSCIL_POS[2]["sampy"]
    }

    tango_io (MICRODIFF_DEVICE, "StartScan4dEx", s4d)
    if (TANGO_ERR) {
      print_tango_err()
      egui_fatal("MD2: error starting the 4d scan.")
      exit
    }
  } else {
    tango_io (MICRODIFF_DEVICE, "StartScanEx", f)
    if (TANGO_ERR) {
      print_tango_err()
      egui_fatal("MD2: error starting the scan.")
      exit
    }
  }
  if (MICRODIFF_DEBUG)
    egui_logmsg("scan started")
  printf(" - command executed in %3.2f ms.\n", 1000*(time()-t0))
  MICRODIFF_OSC = 1
  if (wait_ready() == -1) {
    egui_fatal("MD2: error waiting the motors to move")
    exit
  } else {
    if (MICRODIFF_DEBUG)
      egui_logmsg("scan finished")
    printf(" Scan took %3.2f ms.\n", 1000*(time()-t0))
  }
  MICRODIFF_OSC = 0
  if (flag == 1) {
    tango_put(MICRODIFF_DEVICE,"FastShutterIsEnabled", 1)
    if (TANGO_ERR) {
      print_tango_err()
      egui_fatal("MD2: errror programming the fast shutter.")
      exit
    }
  }
}'
#-------- oscillation end --------
#-------- apertures --------
#%IU% (pos)
#%MDESC% Get/set wich aperture. With pos=0 returns the aperture in use.
#Accepted values 1 and 2. Return value is the aperture name, unknown if error.
def microdiff_aperture_type(pos) '{
local idx st app nb

  if ((MICRODIFF["mdtype"]) {
    eprintf ("microdiff_aperture_type() is deprecated, nothing done\n")
    return(0)
  }
  st = tango_get(MICRODIFF_DEVICE, "AperturesList")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading which aperture.")
    return("unknown")
  }
  nb = split(st,app)
  if (int(pos) <= nb) {
    if (wait_ready() == -1) {
       egui_fatal("MD2: error setting the aperture.")
      return(-1)
    }
    tango_put(MICRODIFF_DEVICE, "CurrentApertureIndex", pos)
    if (TANGO_ERR) {
       print_tango_err()
       egui_fatal("MD2: error setting which aperture.")
       return("unknown")
    }
    return(app[pos-1])
  }

  idx = tango_get(MICRODIFF_DEVICE, "CurrentApertureIndex")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading which aperture.")
    return("unknown")
  }
  #idx is 1 or 2
  return(app[idx-1])
}'

#%IU% (pos)
#%MDESC% Get/set current aperture diameter. With pos=0 returns the current
#aperture diameter. Accepted values 1, 2 and 3. Return value is the aperture
#diameter, -1 if error.
def microdiff_aperture_diameter(pos) '{
local idx st app[] nb

  if (MICRODIFF["mdtype"])
    nb = tango_get(MICRODIFF_DEVICE, "ApertureDiameters",app)
  else
    st = tango_get(MICRODIFF_DEVICE, "AperturesDiameters")
  
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading current aperture diameter.")
    return(-1)
  }

  if (!MICRODIFF["mdtype"])
    nb = split(st,app)
  if (int(pos) > 0) {
    if (nb > 1) {
      if (int(pos) <= nb) {
        if (wait_ready() == -1) {
         egui_fatal("MD2: error setting the aperture diameter.")
         return(-1)
        }
        tango_put(MICRODIFF_DEVICE, "CurrentApertureDiameterIndex", pos)
        if (TANGO_ERR) {
          print_tango_err()
           egui_fatal("MD2: error setting current aperture diameter.")
           return(-1)
        }
        if (wait_ready() == -1) {
         egui_fatal("MD2: error setting the aperture diameter.")
         return(-1)
        }
        return(app[pos-1])
      }
    }
  }
  idx = tango_get(MICRODIFF_DEVICE, "CurrentApertureDiameterIndex")
 
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading current aperture diameter.")
    return(-1)
  }

  if (!MICRODIFF["mdtype"])
    idx -= 1
  return(app[idx])
}'

#%IU% ()
#%MDESC% Return the position of the aperture - in  or out
def _aperturestate() '{
local st

  if (MICRODIFF["mdtype"])
    st = tango_get(MICRODIFF_DEVICE, "AperturePosition")
  else
    st = tango_get(MICRODIFF_DEVICE, "AperturePredefinedPosition")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the beam stop.")
    return("unknown")
  }
  if ((st == 1) || (st == "BEAM"))
    st="IN"
  else if ((st == 2) || (st == "OFF"))
    st="OUT"
  else
    st="unknown"
 
  return(st)
}'

#%IU% (pos)
#%MDESC% Move the aperture to %B%pos%B% on beam (pos=1), out of
#the beam (pos=2).
def microdiff_aperture(pos) '{
local lpos

  if (MICRODIFF["mdtype"]) {
    if (pos == 1)
      lpos = "BEAM"
    else if (pos == 2)
      lpos = "OFF"
    else
      lpos = "PARK"

    tango_put(MICRODIFF_DEVICE, "AperturePosition",lpos)
  } else
    tango_put(MICRODIFF_DEVICE, "AperturePredefinedPosition",pos)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving beamstop")
    return(-1)
  }
  return(0)
}'

#%IU%
#%MDESC% Move the aperture on the beam.
def aperturein '{
local msg

  if (microdiff_aperture(1) < 0)
    exit
  else {
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move aperture on the beam")
    } else {
      msg = _aperturestate()
      egui_logmsg(sprintf ("Aperture is %s", msg))
    }
  }
}'

#%IU%
#%MDESC% Move the aperture out of the beam.
def apertureout '{
local msg

  if (microdiff_aperture(2) < 0)
    exit
  else {
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move aperture out of the beam")
    } else {
      msg = _aperturestate()
      egui_logmsg(sprintf ("Aperture is %s", msg))
    }
  }
}'
#-------- apertures end --------
#-------- anneal --------
def anneal '{
local anneal_time, hutch_status[]
local backst scintst flightst

  if ($# != 1) {
    printf ("Usage:  anneal time[s]\n")
    exit
  }

  anneal_time = $1
  backst = _bsstate()
  scintst = _scintilstate()
  flightst = _flightstate()
  blightst =  _backlightstate()

  if (microdiff_phase(1) < 0) {
    egui_fatal("MD2: Cannot put microdiff in centring phase, exiting...")
    exit
  }
  lightout
  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 ( backst == "IN")
    backin
  if (scuntst == "IN")
    scinton
  if (flighttst == "OFF")
    flightoff()
  if (blightst == "IN")
    lightin
}'

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
}'
#-------- anneal end --------
#-------- scintilator --------
#%IU% (pos)
#%MDESC% Move Scintilator to %B%pos%B% - 1 to put in, 2 to put the photodiode in, 3 to take out of the beam.
def microdiff_scintil(pos) '{
local msg lpos

  if (wait_ready() == -1) {
     egui_fatal("MD2: error movint the scintilator.")
     return(-1)
  }

  if (MICRODIFF["mdtype"]) {
    if (pos == 1)
      lpos = "SCINTILLATOR"
    else if (pos == 2)
      lpos = "PHOTODIODE"
    else
      lpos = "PARK"

    tango_put(MICRODIFF_DEVICE, "ScintillatorPosition",lpos)
  } else 
    tango_put(MICRODIFF_DEVICE, "ScintilPDPredefinedPosition",pos)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving scintilator")
    return(-1)
  }
  return(0)
}'

#%IU% ()
#%MDESC% Return the position of the Scintilator
def _scintilstate() '{
local st

  if (MICRODIFF["mdtype"])
    st = tango_get(MICRODIFF_DEVICE, "ScintillatorPosition")
  else
    st = tango_get(MICRODIFF_DEVICE, "ScintilPDPredefinedPosition")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving the scintilator.")
    return("unknown")
  }
  if ((st == 1) || (st == "SCINTILLATOR"))
    st="IN"
  else if ((st == 3) || (st == "PARK"))
    st="OUT"
  else if ((st == 2) || (st == "PHOTODIODE"))
    st = "PHOTODIODE"
  else
    st="unknown"
 
  return(st)
}'

#%IU%
#%MDESC% Move Scintilator ON beam
def microdiff_scintilon() '{
local msg

  if (microdiff_scintil(1) == -1)
    egui_fatal("MD2: cannot move scintilator onbeam")
  else {
    #wait until movement finished
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move scintilator onbeam")
    } else {
      msg = _scintilstate()
      egui_logmsg(sprintf ("Scintilator %s", msg))
    }
  }
}'

#%IU% ()
#%MDESC% Move Scintilator OFF beam
def microdiff_scintiloff() '{
local msg

  if (microdiff_scintil(3) == -1)
    egui_fatal("MD2: cannot move scintilator offbeam")
  else {
    #wait until movement finished
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move scintilator offbeam")
    } else {
      msg = _scintilstate()
      egui_logmsg(sprintf ("Scintilator %s", msg))
    }
  }
}'

#%UU%
#%MDESC% Move Scintilator ON beam.
def scinton '{
  microdiff_scintilon()
  if (ismacro("local_detector_actions")) {
    local_detector_actions 1
  }
}'

#%UU%
#%MDESC% Move Scintilator OFF beam.
def scintoff '{
  msclose
  microdiff_scintiloff()
  if (ismacro("local_detector_actions")) {
    local_detector_actions 0
  }
}'

#%UU%
#%MDESC% Move photodiode ON beam.
def diodein '{
  if (microdiff_scintil(2) == -1)
    egui_fatal("MD2: cannot move photodiode in")
  else {
    #wait until movement finished
    if (wait_ready() == -1) {
      egui_fatal("MD2: cannot move photodiode in")
    } else {
      msg = _scintilstate()
      egui_logmsg(sprintf ("%s", msg))
    }
  }
}'

#%UU%
#%MDESC% Move photodiode OFF beam.
def diodeout '{
  msclose
  microdiff_scintiloff()
  backin
}'

#%IU% (start)
#%MDESC% Adjust automatically the diode gain, starting from gain %B%start%B%.
def md2diode_adjgain(start) '{
local i ret
local array md2_gainlimit[4]

  md2_gainlimit[0]=0x720
  md2_gainlimit[1:3]=0x6ae

  for (i=start;i<4;i++) {
    md2diode_gainset(i)
    #sleep(2)
    #ct 1
    count_em 0.1; waitcount; getcounts
    ret = S[cnt_num("md2pd")]
    printf("Gain(%d) - count: %3.3f\n", i, ret)
    if (ret < 0) {
      md2diode_gainset(i-1)
      break
    } if (fabs(ret)> md2_gainlimit[i])
      break   
  }
  if (i == 4) {   
    if (ret < 0.01)
       md2diode_gainset(0)
     return 0
  } else
    return(-1)
}'

#%UU% ()
#%MDESC% Read the diode gain. Index id 1=internal diode, 2 = external diode,
#Return the current gain if 0K, -1 if error
def md2diode_gainread() '{
local value

  if (MICRODIFF["mdtype"])
    value = tango_io(MICRODIFF_DEVICE, "getPhotodiodeGain",1)
  else
    value = tango_get(MICRODIFF_DEVICE, "PhDiode1Gain")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading the diode gain.")
    return(-1)
  }
  if (MICRODIFF_DEBUG) {
    tty_cntl("md")
    printf("Current MD2 Diode gain %d", value)
    tty_cntl("me")
  }
  return(value)
}'

#%UU% (value)
#%MDESC% Change the diode gain (values 0, 1, 2, 3).Return the current gain if
#0K, -1 if error
def md2diode_gainset(value) '{
local lvalue

  if (MICRODIFF["mdtype"]) {
    lvalue[0] = 1
    lvalue[1] = value
    tango_io(MICRODIFF_DEVICE, "setPhotodiodeGain", lvalue)
  } else 
    tango_put(MICRODIFF_DEVICE, "PhDiode1Gain", value)
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error changing the diode gain.")
    return(-1)
  }
  return(value)
}'

#-------- scintilator end --------

#-------- front light --------
#%IU% (pos)
#%MDESC% Switch the front light %B%pos%B% off (pos=0) or on (pos=1).
def microdiff_flight(pos) '{

  if ((pos !=0) && (pos != 1))
    return(-1)
  if (wait_ready() == -1) {
     egui_fatal("MD2: error switching the front light.")
     return(-1)
  }
  tango_put(MICRODIFF_DEVICE, "FrontLightIsOn",pos)
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error switching the front light.")
    return(-1)
  }
  return(0)
}'

#%IU% ()
#%MDESC% return the front light status - ON, OFF or unknown.
def _flightstate() '{
local st

  st = tango_get(MICRODIFF_DEVICE,"FrontLightIsOn")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading the front light state.")
    return("unknown")
  }

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

  return(st)
}'

#%IU% ()
#%MDESC% Switch the front light on.
def flighton() '{
local msg

  if (microdiff_flight(1) == 0) {
    msg =  _flightstate()
    egui_logmsg (sprintf("Front light is %s", msg))
  }
  microdiff_flight(1)
}'

#%IU% ()
#%MDESC% Switch the front light off.
def flightoff() '{
local msg

  if (microdiff_flight(0) == 0) {
    msg =  _flightstate()
    egui_logmsg (sprintf("Front light is %s", msg))
  }
}'

#-------- front light end --------
#%IU% (pos)
#%MDESC% Return a string, which corresponds to the %B%pos%B%.
def phase_pos_translate(pos) '{

  if (pos == 1)
    return("Centring")
  if (pos == 2)
    return("BeamLocation")
  if (pos == 4)
    return("DataCollection")
  if (pos == 5)
    return("Transfer")
  return("unknown")
}'

#%IU% (pos)
#%MDESC% Set the microdiff eqipment to different positions %B%pos%B%:
# sample centring (pos=1), beam location (pos=2), data acquisition (pos=4),
# sample transfer (pos=5). Return 0 if set OK, -1 if error or the position
# (if pos = 0).
def microdiff_phase(pos) '{
local lpos

  if (pos == 0) {
    if (MICRODIFF["mdtype"])
      lpos = tango_get(MICRODIFF_DEVICE, "CurrentPhaseIndex")
    else
      lpos = tango_get(MICRODIFF_DEVICE, "PhasePosition")
    if (TANGO_ERR) {
      print_tango_err()
      egui_fatal("MD2: error reading the microdiff phase position")
      return(-1)
    }
    if (MICRODIFF["mdtype"]) {
      if (lpos >=3)
        lpos +=1
    }
    return(lpos)
  }

  if (MICRODIFF["mdtype"]) {
    lpos = phase_pos_translate(pos)
    tango_io(MICRODIFF_DEVICE, "startSetPhase",lpos)
  } else 
    tango_put(MICRODIFF_DEVICE, "PhasePosition",pos)

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error moving microdiff to phase position")
    return(-1)
  }
 if (wait_ready() == -1) {
     egui_fatal("MD2: error moving microdiff to position.")
     return(-1)
  }
  return(0)
}'

#%IU% ()
#%MDESC% Move the oscillation motor to the start angle. Prepare the microdiff
#for data collection. If needed, do a dummy frame to get the dark current time.
def microdiff_preparecollect() '{
local end t0
local stat

  #stat = shstate()
  #if (stat == 4)
  #  shclose

  printf ("-------preparing microdiff for data acquisition\n")

  if ((HELICAL_SCAN4D == 1) && \
      (MXCOLLECT_PARS["experiment_type"] == "classic")) {
    HELICAL_SCAN4D = 0
    HELICAL_OSCIL = 1
  }

  if (HELICAL_SCAN4D == 1) {
    if (helical_check() == -1) {
      #egui_fatal("Start/Final scan positions not set, aborting...")
      exit
    }
  } else if (HELICAL_OSCIL != 0)
    helical_calc()

  #move oscil motor to start angle at the begining of the data collection
  A[OSCIL_MOTOR_NUM] = COLLECT_SEQ["start"] 
  move_em; waitmove; get_angles 

  #msopen

  #prepare the microdiff
  wait_ready()
  if (microdiff_phase(4) < 0) {
    egui_fatal("MD2: error setting microdiff to data collection.")
    return(-1)
  }
  
  #msclose
  #if (stat == 4)
  #  shopen

  if ((COLLECT_SEQ["dark"] == "True") || (COLLECT_SEQ["dark"] == 1)) {
    printf ("Collecting dummy frame to calculate the dark current\n")
    end = COLLECT_SEQ["start"] + COLLECT_SEQ["range"]
    t0 = time()
    if (microdiff_osc_scan(COLLECT_SEQ["start"], end, \
	COLLECT_SEQ["exposure_time"], COLLECT_SEQ["number_of_passes"], 1) \
		== -1) {
      exit
    }
    MXSPEC_PARS["detector"]["DarkTime"] = time()-t0
    printf(" Took %f s\n", MXSPEC_PARS["detector"]["DarkTime"])
    MXSPEC_PARS["detector"]["UseDefaultDarkTime"] = 1
  }

  #switch the front light on
  flighton()

  return(0)
}'

def wait_cleanup '{

  printf ("executing EmergencyStop\n")
  if (MICRODIFF["mdtype"])
    tango_io(MICRODIFF_DEVICE, "abort")
  else
    tango_io(MICRODIFF_DEVICE, "EmergencyStop")

  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: cannot stop the motor.")
    exit
  }
}'

#%IU% ()
#%MDESC% Wait until movement has finished. 
def wait_ready() '{
local stat str

  TANGO_ERR="-1"
  stat = tango_get(MICRODIFF_DEVICE, "State")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: cannot read the microdiff state.")
    return(-1)
  }
  cdef("cleanup_once","wait_cleanup\n","_microdiff_")

  while ((stat == 6) || (stat == 10)) {
    local_wait
    sleep(.100)
    stat = tango_get(MICRODIFF_DEVICE, "State")
  }

  if (tango_get(MICRODIFF_DEVICE, "State") == 8) {
    egui_fatal(tango_get(MICRODIFF_DEVICE, "Status"))
    return (-1)
  }

  if (MICRODIFF["mdtype"]) {
    str = ""
    str = tango_get(MICRODIFF_DEVICE,"LastTaskException")
    if (str) {
      egui_fatal(str)
      return (-1)
    }
  }
  return(0)
}'

#-------- camera parameters --------
#%IU% (calpars)
#%MDESC% Return the pizel/mm values.
def get_cameracalib(calpars) '{

  calpars["x"] = tango_get(MICRODIFF_DEVICE, "CoaxCamScaleX")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading the camera parameters")
    return(-1)
  }
  calpars["y"] = tango_get(MICRODIFF_DEVICE, "CoaxCamScaleY")
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal("MD2: error reading the camera parameters")
    return(-1)
  }
  if (MICRODIFF["mdtype"]) {
    calpars["x"] = 1000000.0*calpars["x"]
    calpars["y"] = 1000000.0*calpars["y"]
  } else {
    calpars["x"] = 1000.0/calpars["x"]
    calpars["y"] = 1000.0/calpars["y"]
  }
  return(0)

}'

def microdiff_take_periodic_backgrounds '{
  local directory filename bkg_mtime

  # find where backgrounds are stored
  if (xml_read(MICRODIFF_HO, "/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)) {
      microdiff_take_backgrounds
    }
    else {
      print "Backgrounds are recent. Nothing to do."
    }
  }
}'

def _microdiff_take_zoom_backgrounds '{
  local directory
  local j
  directory = MICRODIFF["background_files_directory"]

  getangles

  for (j=1; j<=10; j+=1) {
      pos = j
      egui_logmsg(sprintf("  - moving to zoom level %d", j))
      A[zoom]=pos
      move_em; move_poll; wait_ready()

      # take image
      egui_logmsg(sprintf("  - taking background image %d : %s/background%d_%d.tif", j, directory, MICRODIFF["aperture_index"], j))
      if (MICRODIFF["tango_camera"]!="") {
          local idx
          idx = MICRODIFF["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\")\'", MICRODIFF["tango_camera"],directory,idx,j))
      } else {
        local idx
        idx = MICRODIFF["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\")\'", MICRODIFF["camera"], directory, idx, j))
      }
      unix(unix_cmd)
    }
    egui_logmsg("Done !")
}'


def microdiff_take_backgrounds '{
local directory filename bkg_mtime k len i pos
local apertures[] n_apertures

  # find where backgrounds are stored
  if (xml_read(MICRODIFF_HO, "/equipment/autoCentering/imagesFolder") >= 0) {
    directory = XML_tmp[0]["__value__"]
    MICRODIFF["background_files_directory"]=directory

    # now check background 1 file last modification time
    print "taking backgrounds for Automatic Centring... please wait"
    egui_logmsg("Taking backgrounds for Automatic Centring... please wait")

    lightin
    # reset the light factor to 1 to force the default value
    microdiff_light_factor(1)
    backout
    # added to deal with new centring state of MD2
    apertureout

    # move to zoom levels, and take images
    getangles

    n_apertures = tango_get(MICRODIFF_DEVICE, "ApertureDiameters", apertures)
    #split(tango_get(MICRODIFF_DEVICE, "AperturesDiameters"), apertures)
    #n_apertures = asso_len(apertures)
    print n_apertures

    for (i=0; i<n_apertures;i+=1) {
        print "SWITCHING TO APERTURE",i," ",apertures[i]
        microdiff_aperture_diameter(i+1)

        MICRODIFF["aperture_index"]=i

        _microdiff_take_zoom_backgrounds
    }
    egui_logmsg("Done !")
  } else {
    printf("Could not retrieve autocentring information from minidiff XML file\n")
  }
}'
#-------- camera parameters end --------

#-------- minikappa --------
#for kappa_init see minikappa.mac

#%IU% (val)
#%MDESC% Enable (val=1)/disable (val=0) minikappa.
def microdiff_kappaena(val) '{
local str
  (val == 0) ? (str="dis") : (str="en")
  tango_put(MICRODIFF_DEVICE, "KappaIsEnabled",val)
  if (TANGO_ERR) {
    print_tango_err()
    egui_fatal(sprintf("MD2:cannot %able minikappa ",str))
    return(-1)
  }
  wait_ready()
}'
#-------- minikappa end --------

def phi_cleanup '{ }'

cdef ("local_wait","","")

#%IU% ()
#%MDESC% Set all the devices under the cover
def microdiff_cover() '{
  microdiff_scintil(3)
  microdiff_light(0)
  microdiff_beamstop(3)  
  microdiff_aperture(3)
}'

#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% A.Beteva / BLISS%BR%
#$Revision: 2.4 $ $Date: 2014/09/10 08:14:08 $%BR%
#%END%
#%LOG%
#$Log: microdiff.mac,v $
#Revision 2.4  2014/09/10 08:14:08  beteva
#bug fixed in non shutterless helical options
#
#Revision 2.3  2014/01/28 17:26:50  beteva
#cosmetic changes
#
#Revision 2.2  2014/01/22 09:30:21  beteva
#added helical_calc to handle non shutterless mode.
#
#Revision 2.1  2013/05/15 12:24:07  beteva
#changed test for dark current - mxcube2 sends True/False and not
#1/0 any more.
#
#Revision 2.0  2012/11/22 17:13:52  beteva
#changed commands to cope with the new MD2 interface.
#Old interface still usable.
#
#Revision 1.14  2012/11/22 15:04:22  beteva
#added SCAN4D
#
#Revision 1.13  2011/06/28 13:14:56  beteva
#changes in take_backgrounds to cope with the new Auto Centring device server (BL)
#
#Revision 1.12  2011/01/26 09:18:49  guijarro
#added microdiff_get_beamsize and microdiff_get_calibration
#
#Revision 1.11  2010/09/09 13:12:19  beteva
#added microdiff_abort_scan()
#changed the aperture handling to cope with new multiple apertures
#added local_wait in the wait_ready()
#
#Revision 1.10  2010/05/18 14:08:11  beteva
#added photodiode commands
#
#Revision 1.9  2010/04/29 11:06:39  guijarro
#microdiff setup looks at XML file for camera;
#other changes
#
#Revision 1.8  2009/06/02 10:10:54  blissadm
#added microdiff_take_backgrounds macro; do not forget to add MICRODIFF_HO="/udiff" (or equiv.) in setup
#
#Revision 1.7  2009/04/08 11:42:21  beteva
#implemented microdiff_kappaena() to enable/disable minikappa
#
#Revision 1.6  2009/04/06 11:18:42  beteva
#implemented phi_init, kappa_init, zoom_init
#
#Revision 1.5  2009/02/19 12:52:13  beteva
#corrected the aperture parameters, added MICRODIFF_DEBUG and debug printings
#
#Revision 1.4  2009/02/12 16:10:50  beteva
#added putting the microdiff in centring state if abbort acquisition
#
#Revision 1.3  2009/02/09 13:58:41  beteva
#added more commands
#
#Revision 1.2  2008/12/22 14:25:45  beteva
#Changed esrf_io to tango_* calls. Added more commands