esrf

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

#%TITLE% MXPILATUS.mac
#%NAME% %B%mxpilatus.mac%B% - control PILATUS 6M macro set
#for MX datacollection
#%END%

#%UU%
#%MDESC% Set all the nesessary cdefs.
def pilatus_on '{
global CCDSAVE_MODE[] CCDSAVE[]
global PILATUS_SHUT
global PILATUS_DEADTIME

  PILATUS_DEADTIME = 950E-6
  cdef("ccdprep","pilatus_prep","_pxccd",0x20)
  cdef("ccdflush","wait(4);","_pxccd",0x20)
  cdef("ccdfile","pilatus_filename","_pxccd",0x20)
  cdef("ccdstart", "pilatus_start", "_pxccd")
  cdef("ccdread", "", "_pxccd")
  cdef ("local_wait","if (MXCOLLECT_PARS[\"read_status\"]!=1) MXCOLLECT_PARS[\"read_status\"] = 1; pilatus_state", "_pxccd")
  cdef ("user_pollmove",";pilatus_state;", "_pxccd")
  cdef ("specific_collect_frame_hook", "pilatus_postframe_actions", "_pxccd")
  cdef ("local_skip_images","pilatus_skip_images", "_pxccd")
  cdef ("local_set_experiment_type", "pilatus_set_experiment_type", "_pxccd")
  _pilatus_get_bl()
  tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], "timeout",10)
  tango_io(MXSPEC_PARS["detector"]["TangoDeviceName"], "timeout", 10)
  if (whatis("local_abort_scan") == 0)
    eval("def local_abort_scan\'{ }\'")
}'

#%UU%
#%MDESC% Remove the cdefs.
def pilatus_off '{
  cdef("","","_pxccd","delete")
}'

#%IU%
#%MDESC% Set the exposure time and start the detector.
def pilatus_start '{

  TANGO_ERR = "-1"
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_expo_time",\
	COLLECT_SEQ["exposure_time"])
  if (TANGO_ERR) {
    tty_cntl("md")
    print_tango_err()
    tty_cntl("me")
    egui_fatal("Cannot set exposure time, exiting")
  }

  TANGO_ERR = "-1"
  tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], "prepareAcq")
  if (TANGO_ERR) {
    tty_cntl("md")
    print_tango_err()
    tty_cntl("me")
  }

  tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], "startAcq")
  if (TANGO_ERR) {
    tty_cntl("md")
    print_tango_err()
    tty_cntl("me")
    egui_fatal("Cannot start acquisition, exiting")
    exit
  }
}'

#%IU% (dark,start_angle,range,exp_time,number_of_passes,comment)
#%MDESC% Prepare the detector for an acquisition.
def pilatus_prep(dark,start_angle,range,exp_time,number_of_passes,comment) '{
local pilatus_status nb_fr

  detcoverout

  if (range < 0.0001)
    MXCOLLECT_PARS["experiment_type"] = "still"

  printf("Waiting for Pilatus ready\n")
  while(1) {
    TANGO_ERR = "-1"
    pilatus_status = \
	tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_status")
    if (TANGO_ERR) {
      tty_cntl("md")
      print_tango_err()
      tty_cntl("me")
    }
    if (pilatus_status == "Ready") {
      # IDLE
      break
    }
    if (pilatus_status == "Fault") {
      egui_fatal("Pilatus: detector in fault state, exiting datacollection")
      tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], "reset")
      egui_logmsg("Reset the pilatus")
      MXCOLLECT_PARS["experiment_type"] = "classic"
      exit
    }
    sleep(1)
  }
  pilatus_set_threshold(getMxEnergy())
  printf ("PILATUS READY\n")

  TANGO_ERR = "-1"
  if (MXCOLLECT_PARS["experiment_type"] == "still") {
    tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_trigger_mode", \
	"INTERNAL_TRIGGER")
  } else {
    tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_trigger_mode", \
	"EXTERNAL_TRIGGER")
  }
  if (TANGO_ERR) {
    tty_cntl("md")
    print_tango_err()
    tty_cntl("me")
  }
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_mode", \
	"AUTO_FRAME")

  printf("experiment type %s\n", MXCOLLECT_PARS["experiment_type"])
  if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
    nb_fr = COLLECT_SEQ["number_of_images"]
  } else
    nb_fr = 1
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_nb_frames", \
	nb_fr)
}'

#%IU% (cpars,frame)
#%MDESC% Set the file name where the data will be saved. Prepare the header
#and send it to the device server.
def pilatus_filename(cpars,frame) '{
local pilatus_image_number
local suffix prefix_fmt prefix fname
global SAVE_PARAMS
local i angle nb
local pilatus_imagefile
local nb nba cmd dirs ret rdir
local fpar[] img

  unglobal P_HEADER

  suffix = "." getMxDetectorFileSuffix()
  prefix = sprintf("%s_%d_", cpars["fileinfo"]["prefix"], cpars["fileinfo"]["run_number"])

  pilatus_image_number = frame 

  if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
    delete CURRENT_IMAGE["image_number"]
    delete CURRENT_IMAGE["image_file"]
    img =  sprintf("%s/%s%04d%s", cpars["fileinfo"]["directory"], prefix, cpars["start_image_number"], suffix)
    CURRENT_IMAGE["image_file"] = img
    CURRENT_IMAGE["measuredIntensity"] = CURRENT_IMAGE_INTENSITY
    CURRENT_IMAGE["image_number"] = cpars["start_image_number"]
  }

  SAVE_PARAMS["save"] = 0
  delete CURRENT_IMAGE["image_file"]
  delete CURRENT_IMAGE["image_number"]
  SAVE_PARAMS["dir"]=cpars["fileinfo"]["directory"]
  SAVE_PARAMS["number_of_images"] = cpars["number_of_images"]
  SAVE_PARAMS["start_image_number"] = cpars["start_image_number"]
  SAVE_PARAMS["nb_sum_images"] = cpars["nb_sum_images"]
  SAVE_PARAMS["range"]= cpars["range"]

  SAVE_PARAMS["prefix"] = prefix

  rdir = sprintf ("%s%s", PILATUS_BL["buffer"], SAVE_PARAMS["dir"])
  ret = unix(sprintf ("ssh %s@%s mkdir --parents %s", \
             USER, PILATUS_BL["control"], rdir))
  SAVE_PARAMS["ldir"]=rdir

  if ((cpars["number_of_images"] > 4) && (cpars["exposure_time"] < 0.5)) {
    if ((cpars["overlap"] == 0) && \
	(MXCOLLECT_PARS["experiment_type"] == "shutterless")) {
       pilatus_image_number = cpars["start_image_number"]
       printf("image_number shutterless: %d\n", pilatus_image_number)
       # this is automatically done by lbs
       #SAVE_PARAMS["save"] = 1
       # why is this???
       SAVE_PARAMS["number_of_images"] = cpars["number_of_images"]+1
    }
  }

  printf ("experiment type:     %s\n", MXCOLLECT_PARS["experiment_type"])

  if ((MXCOLLECT_PARS["experiment_type"] == "classic") || \
	(MXCOLLECT_PARS["experiment_type"] == "still") || \
	(pilatus_image_number == 0)) {
    nb = pilatus_image_number
    fpar[3] = nb
  } else {
    nb = cpars["number_of_images"]
    fpar[3] = cpars["start_image_number"]

  }

  if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
    nb = cpars["number_of_images"]
    if ((cpars["skip_images"] == 1) && (cpars["file_exists"] != 0)){
       nb = cpars["start_image_number"]
       pilatus_image_number = cpars["number_of_images"]
       printf ("Moving phi to start %f\n", cpars["start"])
       eval (sprintf ("mv phi %f", cpars["start"]))
    }
  }

  #wait pilatus ready
  pilatus_ready()

  #tell the device server which file to save to
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_directory", \
	SAVE_PARAMS["ldir"])
  fpar[0] = SAVE_PARAMS["ldir"]
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_prefix", prefix)
  fpar[1] = prefix
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_suffix", suffix)
  fpar[2] = suffix
  #start image number
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_next_number", \
	fpar[3])
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_index_format", \
	"%04d")
  fpar[4] = "%04d"
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], \
	"saving_overwrite_policy", "OVERWRITE")
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], "saving_format", "CBF")
  fpar[5] = "y"

  pilatus_imagefile = sprintf("%s/%s%04d%s", \
	SAVE_PARAMS["dir"], prefix, nb, suffix)


  # But also set the PILATUS parameters for pilatussave
  global P_HEADER

  ab = time()  pilatus_static_header(cpars)

  if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
    nb_img = PILATUS_HEADER["N_oscillations"]
  } else {
    nb_img = 1
  }
  for (i = 0; i<nb_img; i++) {
    angle = getMxCollectPars("current_phi") + \
	i * cpars["range"]
    PILATUS_HEADER["Start_angle"] = sprintf("%f deg.", angle)
  

    header = ""
    header = sprintf("\n%s\n",  PILATUS_BL["serial"])
    header = sprintf ("%s# %s\n", header, date("%Y/%b/%d %T.%.3"))
    header = sprintf ("%s# Pixel_size 172e-6 m x 172e-6 m\n", header)
    header = sprintf ("%s# Silicon sensor, thickness 0.000320 m\n", header)
    for (k in PILATUS_HEADER) {
      header = sprintf ("%s# %s %s\n", header, k, PILATUS_HEADER[k])
    }
    header = "array_data/header_contents|" header ";"
    P_HEADER[i]= sprintf ("%d : %s", i, header)
  }

  delimiter[0] = "|"
  delimiter[1] = ";"
  delimiter[2] = ":"
  tango_put(MXSPEC_PARS["detector"]["LimaDeviceName"], \
	"saving_header_delimiter", delimiter)
  tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], \
	"setImageHeader", P_HEADER)
  
  printf ("time1 %.3f\n", time()-ab)

  printf ("Image file %s\n", pilatus_imagefile)

  if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
    pilatus_create_thumbnails(SAVE_PARAMS["dir"], prefix, \
  	cpars["start_image_number"], cpars["number_of_images"])
  } else {
    pilatus_create_thumbnails(SAVE_PARAMS["dir"], prefix, \
    	fpar[3])
  }

  return(pilatus_imagefile)
}'

#%IU% ()
#%MDESC% For using the adxv program with the pilatus software
#when images are saved.
def pilatus_adxv_notify() '{
global PILATUS_NOTIFY_FILE PILATUS_NOTIFY_RUN

  PILATUS_NOTIFY_FILE = MXCOLLECT_PARS["adxv_notify_file"]
  PILATUS_NOTIFY_RUN += 1

  tmpfile = "/tmp/adxv_notify"

  fprintf(tmpfile,"%d %s", PILATUS_NOTIFY_RUN, PILATUS_FILENAME)
  close(tmpfile)
  unix(sprintf("cp %s %s;/bin/rm %s", tmpfile, PILATUS_NOTIFY_FILE, tmpfile)) 
}'

#%IU% (energy)
#%MDESC% Set the detector threshold as function of the half and the gais as
#function of the current %B%energy%B% [KeV]. The lower energy, the higher the
#gain. Do not wait for the execution.
def _pilatus_set_threshold(egy) '{
local old_en

  if (PILATUS_BL["minE"] == 0)
     PILATUS_BL["minE"] = 6.55

  #the camserver minimum energy is PILATUS_BL["minE"]
  if (egy < PILATUS_BL["minE"])
    egy = PILATUS_BL["minE"]

  old_en = \
  	tango_get(MXSPEC_PARS["detector"]["TangoDeviceName"],"working_energy")
  if (fabs (egy - old_en) > 0.1) {
    tango_put(MXSPEC_PARS["detector"]["TangoDeviceName"],"working_energy", egy)
    if (TANGO_ERR) {
      tty_cntl("md")
      print_tango_err()
      tty_cntl("me")
      return (-1)
    }
  return(0)
  }
}'
#%IU% (energy)
#%MDESC% Set the detector threshold as function of the half and the gais as
#function of the current %B%energy%B% [KeV]. The lower energy, the higher the
#gain. Wait until threshold and gain set.
def pilatus_set_threshold(egy) '{
local old_en set_en
    
  printf("Setting Pilatus detector energy threshold and gain\n")

  #the camserver minimum energy is PILATUS_BL["minE"]
  if (egy < PILATUS_BL["minE"])
    egy = PILATUS_BL["minE"]

  if (_pilatus_set_threshold(egy) == -1)
    exit
  old_en = \
	tango_get(MXSPEC_PARS["detector"]["TangoDeviceName"],"working_energy")
  while(fabs (egy - old_en) > 0.1) {
    printf("Still setting the threshold, please wait...\n")
    sleep(5)
    old_en = \
	tango_get(MXSPEC_PARS["detector"]["TangoDeviceName"],"working_energy")
    if (TANGO_ERR) {
      tty_cntl("md")
      print_tango_err()
      tty_cntl("me")
      exit
    }
  }
  PILATUS_THRESHOLD = \
	tango_get(MXSPEC_PARS["detector"]["TangoDeviceName"],"threshold")
  tango_put(MXSPEC_PARS["detector"]["TangoDeviceName"], "fill_mode", "ON")
  if (TANGO_ERR) {
      tty_cntl("md")
      print_tango_err()
      tty_cntl("me")
  }
}'

#%IU% (energy)
#%MDESC% Set the detector threshold as function of the half and the gais as
#function of the current %B%energy%B% [KeV]. The lower energy, the higher the
#gain.
def pilatus_set_threshold_old(egy) '{
local old_threshold energy gg
global PILATUS_THRESHOLD
local old_gain
  
  printf("Setting Pilatus detector energy threshold and gain\n")
  
  if (egy > 6.7)
    energy = egy*600
  else
    energy = 4000
    
  old_threshold = \
  	tango_get(MXSPEC_PARS["detector"]["TangoDeviceName"],"threshold")
  PILATUS_THRESHOLD = int(old_threshold+0.5)
  if (fabs(energy - old_threshold) > 200) {
    printf("\t -> setting pilatus  threshold to %f eV\n", energy)
    tango_put(MXSPEC_PARS["detector"]["TangoDeviceName"], \
	"threshold", energy)
     if (TANGO_ERR) {
       tty_cntl("md")
       print_tango_err()
       tty_cntl("me")
       return (-1)
     }
    PILATUS_THRESHOLD = int(energy+0.5)
  } else{
    printf("\t-> pilatus threshold is set to %f eV\n", old_threshold)
  }

#  old_gain = \
#	tango_get(MXSPEC_PARS["detector"]["TangoDeviceName"],"Threshold_gain")
  if (egy > 12) {
    printf("  -> setting low gain\n")
    gg = 0
  } else if ((egy > 8) && (egy <= 12)) {
    printf("  -> setting mid gain\n")
    gg = 1
  } else if ((egy >= 6) && (egy <= 8)) {
    printf("  -> setting high gain\n")
    gg = 2
  } else {
    printf("  -> setting ultra high gain\n")
    gg = 3
  }
  if (old_gain == gain)
    return(0)
  tango_put(MXSPEC_PARS["detector"]["TangoDeviceName"], "Threshold_gain", gg)
  if (TANGO_ERR) {
    tty_cntl("md")
    print_tango_err()
    tty_cntl("me")
    return (-1)
  }
  return(0)
}'

#%IU%()
#%MDESC% Check the detector state. Exit if fault state. Stop the acquisition
#in mxCuBE.
def pilatus_ready() '{
local stat

  TANGO_ERR = "-1"
  stat = tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_status")
  if (TANGO_ERR) {
    tty_cntl("md")
    print_tango_err()
    tty_cntl("me")
    egui_fatal("Pilatus: detector cannot read state, exiting datacollection")
    msclose
    egui_logmsg("Closed the fast shutter")
    MXCOLLECT_PARS["experiment_type"] = "classic"
    exit
  }

  if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
    if (stat == "Fault") {
      msclose
      egui_logmsg("Closed the fast shutter")
      CURRENT_IMAGE["image_number"] = \
	tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], "last_image_saved")
      cmd = sprintf ("Pilatus: detector in fault state, exiting datacollection at image number %d", CURRENT_IMAGE["image_number"]-1)

      egui_fatal(cmd)
      if (CURRENT_IMAGE["image_number"] > 2) {
        #start copying the acquired images
        SAVE_PARAMS["number_of_images"] = CURRENT_IMAGE["image_number"]-1
        pilatus_cp_files ()
      }  
      #reset the pilatus detector
      tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], "reset")
      egui_logmsg("Reset the pilatus")
      printf ("Reset the pilatus with %d images\n", SAVE_PARAMS["number_of_images"])
      local_abort_scan
      egui_logmsg("Aborted the scan")
      MXCOLLECT_PARS["experiment_type"] = "classic"
      exit
    }
  }
  if ((MXCOLLECT_PARS["experiment_type"] == "classic") || \
	(MXCOLLECT_PARS["experiment_type"] == "still")) {
    while (stat == "Running") {
      #waiting for pilatus to finish acquisition
      sleep(1)
      stat = tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_status")
    }
  }
}'

#%IU%
#%MDESC% Check the detector state. Exit if fault state. Stop the acquisition
#in mxCuBE.
def pilatus_state '{
local stat lfile imgfile lt msg
global LAST_FRAME_NUMBER

  if (MXCOLLECT_PARS["read_status"]) {
    TANGO_ERR = "-1"
    stat = tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_status")
    if (TANGO_ERR) {
      tty_cntl("md")
      print_tango_err()
      tty_cntl("me")
      egui_fatal("Pilatus: detector cannot read state, exiting datacollection")
      if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
        shclose
        egui_logmsg("Closed the safety shutter")
        MXCOLLECT_PARS["experiment_type"] = "classic"
      } else {
        msclose
        egui_logmsg("Closed the fast shutter")
      }
      exit
    }

    if (MXCOLLECT_PARS["experiment_type"] == "shutterless") {
      if (stat == "Fault") {
        shclose
        egui_logmsg("Closed the safety shutter")
        CURRENT_IMAGE["image_number"] = \
		tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], \
		"last_image_saved")
        msg = "Pilatus: detector in fault state, exiting datacollection"
        msg = sprintf ("%s at image number %d", msg,CURRENT_IMAGE["image_number"]-1)

        egui_fatal(msg)
        if (CURRENT_IMAGE["image_number"] > 2) {
          #start copying the acquired images
          SAVE_PARAMS["number_of_images"] = CURRENT_IMAGE["image_number"]-1
          pilatus_cp_files ()
        }  
        #reset the pilatus detector
        tango_io(MXSPEC_PARS["detector"]["LimaDeviceName"], "reset")
        egui_logmsg("Reset the pilatus")
        printf ("Reset the pilatus with %d images\n", \
	  SAVE_PARAMS["number_of_images"])
        local_abort_scan
        egui_logmsg("Aborted the scan")
        MXCOLLECT_PARS["experiment_type"] = "classic"
        exit
      }
      if (stat == "Running") {
        sleep(1)
        CURRENT_FRAME_NUMBER = \
		tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], \
		"last_image_saved")
        if ((CURRENT_FRAME_NUMBER > 0) && \
		(CURRENT_IMAGE["image_number"] != CURRENT_FRAME_NUMBER)) {
          delete CURRENT_IMAGE["image_number"]
          delete CURRENT_IMAGE["image_file"]
          printf ("--------> frame %d\n", CURRENT_FRAME_NUMBER)

          lt = time() - SAVE_PARAMS["start_time"]
          lfile = sprintf ("%s%04d.%s", SAVE_PARAMS["prefix"], \
	    CURRENT_FRAME_NUMBER, COLLECT_SEQ["fileinfo"]["suffix"])
          if ((MXCOLLECT_PARS["experiment_type"] == "shutterless") && \
		(CURRENT_FRAME_NUMBER < SAVE_PARAMS["number_of_images"]-1)) {
            CURRENT_IMAGE["image_number"] = CURRENT_FRAME_NUMBER
            CURRENT_IMAGE["measuredIntensity"] = CURRENT_IMAGE_INTENSITY
            CURRENT_IMAGE["image_file"] = sprintf("%s/%s", \
		SAVE_PARAMS["dir"], lfile)
            printf("-----------> %s\n", CURRENT_IMAGE["image_file"])
          }
          imgfile = sprintf ("load_image %s/%s\n", SAVE_PARAMS["ldir"], lfile)
          #printf ("current image file %s\n", imgfile)
          if (commented) {
          if (sock_par(sprintf("%s:8100", PILATUS_BL["gate"]), \
		"connect", "silent") != 0) {
            sock_put(sprintf("%s:8100", PILATUS_BL["gate"]), imgfile)
            sock_par(sprintf("%s:8100", PILATUS_BL["gate"]), "close")
          }
          }
        }
      } 
    } else if ((MXCOLLECT_PARS["experiment_type"] == "classic") || \
	(MXCOLLECT_PARS["experiment_type"] == "still")) {
      while (stat == "Running") {
        #waiting for pilatus to finish acquisition
        sleep(1)
        stat = tango_get(MXSPEC_PARS["detector"]["LimaDeviceName"], "acq_status")
      }
    }
  }
}'

def pilatus_header_all() '{
local i angle

  unglobal P_HEADER
  global P_HEADER

  for (i = 0; i<PILATUS_HEADER["N_oscillations"]; i++) {
    angle = getMxCollectPars("current_phi") + \
	i * cpars["range"]
    PILATUS_HEADER["Start_angle"] = sprintf("%f deg.", angle)
    P_HEADER[i]= sprintf ("%d : %s", i, )
  }
}'



def pilatus_static_header(cpars) '{
unglobal PILATUS_HEADER
global PILATUS_HEADER

  PILATUS_HEADER["file_comments"]= cpars["comment"]
  PILATUS_HEADER["N_oscillations"] = cpars["number_of_images"]
  PILATUS_HEADER["Oscillation_axis"] = "omega"
  PILATUS_HEADER["Chi"] = "0.0000 deg."
  PILATUS_HEADER["Phi"] = sprintf ("%0.4f deg.", A[kap2])
  PILATUS_HEADER["Kappa"] = sprintf ("%0.4f deg.", A[kap1])
  PILATUS_HEADER["Alpha"] = "0.0000 deg."
  PILATUS_HEADER["Polarization"] = getMxBcmPars("polarisation")
  PILATUS_HEADER["Detector_2theta"] = "0.0000 deg."
  PILATUS_HEADER["Angle_increment"]= sprintf("%0.4f deg.", cpars["range"])
  #PILATUS_HEADER["Start_angle"] = \
  #	sprintf("%f deg.", getMxCollectPars("current_phi"))
  PILATUS_HEADER["Transmission"] = ATT_FACTOR
  PILATUS_HEADER["Flux"] = sprintf("%e ph/s", S[flux_i0])
  PILATUS_HEADER["Beam_xy"] = sprintf("(%.2f, %.2f) pixels", \
	getMxBeamCentreX()/MXBCM_PARS["detector"]["px"], \
	getMxBeamCentreY()/MXBCM_PARS["detector"]["py"])
  PILATUS_HEADER["Detector_Voffset"] = "0.0000 m"
  PILATUS_HEADER["Energy_range"] = "(0, 0) eV"
  PILATUS_HEADER["Detector_distance"] = \
	sprintf("%f m", getMxCurrentDistance()/1000.0)
  PILATUS_HEADER["Wavelength"] = sprintf("%f A", getMxWavelength())
  PILATUS_HEADER["Trim_directory:"] = "(nil)"
  PILATUS_HEADER["Flat_field:"] = " (nil)"
  PILATUS_HEADER["Excluded_pixels:"] = " badpix_mask.tif"
  PILATUS_HEADER["N_excluded_pixels"] = "= 321"
  PILATUS_HEADER["Threshold_setting"] = sprintf ("%d eV", PILATUS_THRESHOLD)
  PILATUS_HEADER["Count_cutoff"] = "1048500"
  PILATUS_HEADER["Tau"] = "= 0 s"
  PILATUS_HEADER["Exposure_period"] =  \
	sprintf("%f s", (cpars["exposure_time"]+PILATUS_DEADTIME))
  PILATUS_HEADER["Exposure_time"] = sprintf("%f s", cpars["exposure_time"])
}'

def pilatus_header(cpars) '{
global PILATUS_HEADER

  # But also set the PILATUS parameters for pilatussave
  PILATUS_HEADER["file_comments"]= cpars["comment"]
  PILATUS_HEADER["N_oscillations"] = cpars["number_of_images"]
  PILATUS_HEADER["Oscillation_axis"] = "omega"
  PILATUS_HEADER["Chi"] = "0.0000 deg."
  PILATUS_HEADER["Phi"] = sprintf ("%0.4f deg.", A[kap2])
  PILATUS_HEADER["Kappa"] = sprintf ("%0.4f deg.", A[kap1])
  PILATUS_HEADER["Alpha"] = "0.0000 deg."
  PILATUS_HEADER["Polarization"] = getMxBcmPars("polarisation")
  PILATUS_HEADER["Detector_2theta"] = "0.0000 deg."
  PILATUS_HEADER["Angle_increment"]= sprintf("%0.4f deg.", cpars["range"])
  PILATUS_HEADER["Start_angle"] = \
	sprintf("%f deg.", angle)
  PILATUS_HEADER["Transmission"] = ATT_FACTOR
  PILATUS_HEADER["Flux"] = sprintf("%e ph/s", S[flux_i0])
  PILATUS_HEADER["Beam_xy"] = sprintf("(%.2f, %.2f) pixels", \
	getMxBeamCentreY()/MXBCM_PARS["detector"]["py"], \
	getMxBeamCentreX()/MXBCM_PARS["detector"]["px"])
  PILATUS_HEADER["Detector_Voffset"] = "0.0000 m"
  PILATUS_HEADER["Energy_range"] = "(0, 0) eV"
  PILATUS_HEADER["Detector_distance"] = \
	sprintf("%f m", getMxCurrentDistance()/1000.0)
  PILATUS_HEADER["Wavelength"] = sprintf("%f A", getMxWavelength())
  PILATUS_HEADER["Trim_directory:"] = "(nil)"
  PILATUS_HEADER["Flat_field:"] = " (nil)"
  PILATUS_HEADER["Excluded_pixels:"] = " badpix_mask.tif"
  PILATUS_HEADER["N_excluded_pixels"] = "= 321"
  PILATUS_HEADER["Threshold_setting"] = sprintf ("%d eV", PILATUS_THRESHOLD)
  PILATUS_HEADER["Count_cutoff"] = "1048500"
  PILATUS_HEADER["Tau"] = "= 0 s"
  PILATUS_HEADER["Exposure_period"] =  \
	sprintf("%f s", (cpars["exposure_time"]+0.003))
  PILATUS_HEADER["Exposure_time"] = sprintf("%f s", cpars["exposure_time"])
  header = sprintf("\n%s\n",  PILATUS_BL["serial"])
  header = sprintf ("%s# %s\n", header, date("%Y/%b/%d %T.%.3"))
  header = sprintf ("%s# Pixel_size 172e-6 m x 172e-6 m\n", header)
  header = sprintf ("%s# Silicon sensor, thickness 0.000320 m\n", header)

  for (k in PILATUS_HEADER) {
    header = sprintf ("%s# %s %s\n", header, k, PILATUS_HEADER[k])
  }
  header = "array_data/header_contents|" header ";"

  return(header)
}'

#%IU% ()
#%MDESC% Skip images already taken - the pilatus 6M shutterless mode specific.
def pilatus_skip_images() '{

  if (COLLECT_SEQ["shutterless"] == 1) {
    if (COLLECT_SEQ["skip_images"] == 1 && COLLECT_SEQ["file_exists"] != 0) {
      COLLECT_SEQ["number_of_images"] -= COLLECT_SEQ["file_exists"]
      COLLECT_SEQ["start"] += COLLECT_SEQ["range"]*COLLECT_SEQ["file_exists"]
      if (COLLECT_SEQ["start_image_number"] != 0)
        COLLECT_SEQ["start_image_number"] += COLLECT_SEQ["file_exists"]
      else
        COLLECT_SEQ["start_image_number"] = COLLECT_SEQ["file_exists"] + 1
       
    }
  }
}'

#%IU% ()
#%MDESC% Set the experiment type according to the collect parameters - pilatus
#6M shutterless mode specific.
def pilatus_set_experiment_type() '{

  if (PILATUS_SHUT) {
    if (index(COLLECT_SEQ["experiment_type"],"Inverse") > 0)
      COLLECT_SEQ["experiment_type"] = "shutterless Inv"
    MXCOLLECT_PARS["experiment_type"] = "shutterless"
    if (COLLECT_SEQ["overlap"] != 0)
      MXCOLLECT_PARS["experiment_type"] = "classic"
  } else {
    MXCOLLECT_PARS["experiment_type"] = "classic"
  }

}'

#%IU% ()
#%MDESC% Actions to be taken after the acquisition sequence ends,
def pilatus_postframe_actions() '{
  pilatus_cp_files ()
  if (HELICAL_OSCIL == 0)
    pilatus_sum_images()
}'

#%IU% ()
#%MDESC% Start a script to copy the data files from the local disk to nice.
def pilatus_cp_files () '{
local cmd

  SAVE_PARAMS["save"] = 0
  if (SAVE_PARAMS["save"] == 1) {
    cmd = sprintf ("/users/blissadm/local/bin/pilatus_copyfiles %s %s %s %d %d %s", \
	SAVE_PARAMS["dir"], SAVE_PARAMS["prefix"], \
	getMxDetectorFileSuffix(), SAVE_PARAMS["number_of_images"], \
	SAVE_PARAMS["start_image_number"], SAVE_PARAMS["ldir"])
    printf ("%s\n", cmd)
    unix (cmd)
  }
  SAVE_PARAMS["save"] = 0
}'

#%IU% ()
#%MDESC% Start a script to sum images.
def pilatus_sum_images() '{
local cmd dirs sumdir

  if (SAVE_PARAMS["nb_sum_images"] > 0) {
    split(SAVE_PARAMS["dir"], dirs, "RAW_DATA")
    sumdir = sprintf ("%s/SUMMED_DATA/%s", dirs[0], dirs[1])
    if (file_info(sumdir, "isdir") == 0) {
      if (unix(sprintf ("mkdir -p %s", sumdir)) != 0)
        return(-1)
    }
    cmd = sprintf ("/users/blissadm/local/bin/pilatus_mergeimages %s %s %s %d %d %d %g %s", \
	SAVE_PARAMS["dir"], SAVE_PARAMS["prefix"], \
	getMxDetectorFileSuffix(), (SAVE_PARAMS["number_of_images"]-1),\
	SAVE_PARAMS["start_image_number"], SAVE_PARAMS["nb_sum_images"], \
	SAVE_PARAMS["range"], sumdir)
    printf ("%s\n", cmd)
    unix (cmd)
  }
}'

#%IU% (dir, prefix, start_img, nb_img)
#%MDESC%Start a script which creates thumbnails from the cbf files.
def pilatus_create_thumbnails(dir, prefix, start_img, nb_img) '{
local cmd fname

  fname[0]= sprintf ("%s%04d.%s", prefix, start_img, getMxDetectorFileSuffix())
  #fname[0]= sprintf ("%s%04d.%s", SAVE_PARAMS["prefix"], \
	#SAVE_PARAMS["start_image_number"], getMxDetectorFileSuffix())

  if (nb_img > 1) {
    fname[1] = sprintf ("%s%04d.%s", prefix, nb_img, getMxDetectorFileSuffix())
    #fname[1] = sprintf ("%s%04d.%s", SAVE_PARAMS["prefix"], \
	#SAVE_PARAMS["number_of_images"]-1, getMxDetectorFileSuffix())
    cmd = sprintf("/users/blissadm/local/bin/%s_create_thumbnail.nice %s %s %s", \
	PILATUS_BL["blname"], dir,  fname[0], fname[1])
	#SAVE_PARAMS["dir"], fname[0], fname[1])
  } else {
    cmd =  sprintf("/users/blissadm/local/bin/%s_create_thumbnail.nice %s %s %s", \
	PILATUS_BL["blname"], dir,  fname[0], fname[0])
  }
  printf ("%s\n", cmd)
  unix (cmd)
}'

#%IMACROS%
#%MACROS%
#%TOC%
#%AUTHOR% A.Beteva/BLISS
#$Revision: 2.6 $$Date: 2014/02/12 16:21:14 $
#%END%

#### Macros for testing only ####
def p_header(angle) '{
global string array PP_HEADER[31][64]
local i header

  PP_HEADER[0] = sprintf("\n%s\n",  PILATUS_BL["serial"])
  PP_HEADER[1] = "# " date("%Y/%b/%d %T.%.3")
  PP_HEADER[2] = "# Pixel_size 172e-6 m x 172e-6 m"
  PP_HEADER[3] = "# Silicon sensor, thickness 0.000320 m"
  PP_HEADER[4] = sprintf("# Exposure_time %0.4f s", cpars["exposure_time"])
  PP_HEADER[5] = \
	sprintf("# Exposure_period 0.4%f s", (cpars["exposure_time"]+0.003))
  PP_HEADER[6] = "# Tau = 0 s"
  PP_HEADER[7] = "# Count_cutoff 1048500"
  PP_HEADER[8] = sprintf ("# Threshold_setting %d eV", PILATUS_THRESHOLD)
  PP_HEADER[9] = "# N_excluded_pixels = 321"
  PP_HEADER[10] = "# Excluded_pixels:  badpix_mask.tif"
  PP_HEADER[11] = "# Flat_field:  (nil)"
  PP_HEADER[12] = "# Trim_directory: (nil)"
  PP_HEADER[13] = sprintf("# Wavelength %f A", getMxWavelength())
  PP_HEADER[14] = \
	sprintf("# Detector_distance %f m", getMxCurrentDistance()/1000.0)
  PP_HEADER[15] = "# Energy_range (0, 0) eV"
  PP_HEADER[16] = "# Detector_Voffset 0.0000 m"
  PP_HEADER[17] = sprintf("# Beam_xy (%.2f, %.2f) pixels",1222.98, 1257.31)
  PP_HEADER[18] = sprintf("# Flux %e ph/s", S[flux_i0])
  PP_HEADER[19] = sprintf ("# Transmission %f", ATT_FACTOR)
  PP_HEADER[20] = sprintf("# Start_angle %0.4f deg.",angle)
  PP_HEADER[21] = sprintf("# Angle_increment %f deg.", cpars["range"])
  PP_HEADER[22] = "# Detector_2theta 0.0000 deg."
  PP_HEADER[23] = sprintf ("# Polarization %g", getMxBcmPars("polarisation"))
  PP_HEADER[24] = "# Alpha 0.0000 deg."
  PP_HEADER[25] = sprintf ("# Kappa %f deg.", A[kap1])
  PP_HEADER[26] = sprintf ("# Phi %f deg.", A[kap2])
  PP_HEADER[27] = "# Chi 0.0000 deg."
  PP_HEADER[28] = "# Oscillation_axis omega"
  PP_HEADER[29] = sprintf ("# N_oscillations %d", cpars["number_of_images"])
  PP_HEADER[30] = sprintf ("# file_comments %s",cpars["comment"])
  for(i=0; i<31; i++)
    header = sprintf ("%s%s\n", header, PP_HEADER[i])
  return(header)
}'
#### Macros for testing only END ####

#%LOG%
#$Log: mxpilatus.mac,v $
#Revision 2.6  2014/02/12 16:21:14  guijarro
#added deatime variable
#never try to save files directly
#fix for the beam position in heder
#
#Revision 2.5  2013/10/24 13:00:55  guijarro
#do not send too many events in local_wait
#
#Revision 2.4  2013/04/15 08:18:18  beteva
#added "silent" (do not print errors) option for the socket connection with ADXV
#
#Revision 2.3  2013/02/18 13:56:09  beteva
#introduced PILATUS_BL["minE"] as min threshold energy is different for
#each detector.
#
#Revision 2.2  2012/11/29 15:19:45  beteva
#added the still experiment type - the only one to use the internal trigger.
#
#Revision 2.1  2012/11/28 12:44:49  beteva
#set the type to classic if still acquisition
#fixed bug for trigger setting if classic data collect
#
#Revision 2.0  2012/11/23 09:39:33  beteva
#changed interface from Taco to Tango
#
#Revision 1.6  2012/09/07 13:58:38  guijarro
#changes for the new Pilatus server
#
#Revision 1.5  2012/05/30 10:31:22  guijarro
#changes from ID29: sum instead of merge
#
#Revision 1.4  2012/01/30 10:36:35  beteva
#removed some old/comented parts
#
#Revision 1.3  2012/01/27 14:59:38  beteva
#added pilatus_skip_images
#
#Revision 1.2  2011/11/30 10:03:56  beteva
#added more functionality, error check and scripts to start
#
#Revision 1.1  2010/09/10 08:41:53  beteva
#Initial revision
#