esrf

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

#%TITLE% MAR345.MAC
#%NAME% 
#    MAR Research scanner commands and utilities.
#
#%CATEGORY% Ccd, Detection
#
#%DESCRIPTION%
#   The MAR345 scanner provides a X-ray detection area from 180 to 345 mm with two possible
#   pixel sizes 100 and 150 micro-meter. This scanner is using a unique image-plate that is
#   erased after each exposure-read-out cycle. This is why the mar is used as detector  and
#   not as a offline scanner. 
#   Read-out cycles range from 108 to 34 (!!!) seconds, depending on pixel size and scanned
#   plate diameter. This is about 3 times faster than other scanners and actually comes 
#   close to the performance of CCD-detectors.
#%BR%
#    a TACO device server named MarScan345ds is running on the MAR computer and
#    controls the scanner. 
#
#%OVERVIEW%
#%BR%
#   These user macros allow full control of the scanner for doing single scan, enabling spec scan with the mar like pseudo-counter or starting a data collection with spindle/shutter synchronisation. 
#%DL%
#%DT%marsetup%DD%  setup parameters to get control of the mar
#%DT%marnewfile%DD% set the image filename parameters
#%DT%maron%DD%   set on the use of the mar with the spec scan commands
#%DT%maroff%DD%   set off the mar use with the spec scan commands
#%DT%marscan%DD%   scan the Image Plate.
#%DT%marread%DD%  read the image and display it with dis GUI
#%DT%marerase%DD%  erase the Image Plate.
#%DT%marformat%DD% change the image saved-format.
#%DT%marmode%DD%   set the image size.
#%DT%maroptpar%DD% set the the optional parameters that will be saved into the file header
#%DT%marcollect%DD%  Perform a data collection

#%XDL%
#
#%LOG%
#$Log: mar345.mac,v $
#Revision 2.4  2008/07/31 06:53:25  rey
#documentation changes
#
#Revision 2.3  2004/03/09 09:37:07  claustre
#removed all the rdefs on ccd macros
#
#Revision 2.2  2002/04/29 13:20:22  claustre
#few bug fixed, plus maroptpar new macro
#
#Revision 2.1  2000/09/11 09:06:58  rey
#New stable version with CCD-like macros
#
#                     
#%END%

#%UU%
#%MDESC%
#   Setup parameters for MAR345 scanner
def marsetup '{

   global MAR_DEV MARHOME MAR_SCANHOME
   global MAR_DISABLED MAR_CMDID
   global MAR_FORMAT
   global MAR_SCANDATADIR MAR_DATADIR MAR_IMAGEDIR MAR_SUFFIX
   global MAR_N MAR_FILEPREFIX MAR_PREFIX MAR_OVRW
   global MAR_COLLECT 
   global MAR_DIST MAR_WAV

   if (whatis("MAR_DEV") & 0x8000000) {
      MAR_DEV = "ID9/mar345/111"      
   }

   if ($#){
      MAR_DEV		= "$1"
      
   }else {
      MAR_DEV=getval("MAR device name",MAR_DEV)
   }
   #
   # Check that the server is running 
   #
   MAR_DISABLED=0

   if (esrf_io(MAR_DEV,"DevState") == -1 ) {
       tty_cntl("md")
       print "   <MAR345> - device server not responding. "
       print "           MAR operation disabled"
       tty_cntl("me")
       MAR_DISABLED = 1
   }
   esrf_io(MAR_DEV,"timeout",10)
    
}'


#%UU%
#%MDESC%
#   Activate marscan during scan acquisitions
def maron '{
  global MARON
  
  if (MAR_DISABLED) { 
     print "   <MAR345> Disabled. Command ignored."
  }else {
    MARON=1
    MAR_COLLECT = 0

    printf("\n   <MAR345> Filename setting:\n")
    tty_cntl("md")
    printf("   - %s (mar computer)\n\n",mar_getfilename())
    tty_cntl("me")

    cdef("user_getcounts","_marscan\n","_mar_") 
    cdef("prompt_mac",     "mar_prompt\n","_mar_") 
  }
}'

#%UU%
#%MDESC%
#   Deactivate marscan during scan acquisitions
def maroff '{
  if (MAR_DISABLED) { 
     print "   <MAR345> Disabled. Command ignored."
  }else {
    MARON=0
    cdef("user_getcounts","","_mar_","delete")
  }
}'

#%UU% ["frame number"] ["image directory"] ["filename prefix"] 
#%MDESC%
#   Starts a scan command on MAR 345 scanner
#
def marscan '{

   local command dir_flag
   MAR_COLLECT = 0

   if (MAR_DISABLED) { 
      print "   <MAR345> Disabled. Command ignored."
   }else {
     printf("\n   <MAR345> Filename setting:\n")
     tty_cntl("md")
     printf("   - %s (mar computer)\n\n",mar_getfilename())
     tty_cntl("me")

     _marscan
  }
}'


#%UU% [binning factor]
#%MDESC%
#   read the last image by applying binning reduction and display it.
#
def marread '{
  local _sz
  if (MAR_DISABLED) { 
     print "   <MAR345> Disabled. Command ignored."
  }else {
   if ($#==0 || $1 <1 || $1>10) {
     p "usage: marread <1..10>"
     exit
   }
    # get first the row and column size, do not forget here the
    # boundery effects !!
    _sz = 1 + int((esrf_io(MAR_DEV,"DevScannerGetMode")-1) / $1)
     shared ushort array image_data0[_sz][_sz]

     # for huge image tcp protocol is needed
     esrf_io(MAR_DEV,"tcp")   
     esrf_io(MAR_DEV,"DevScannerRead", $1, image_data0)
     # swap data if plateform is not linux (little endian)
     if (!index(getenv("OSTYPE"), "linux")) {
       array_op("swap",image_data0)
     }
     # force disp to update the image displayed !!!
     image_data0[0][0]=image_data0[0][0]
  }  
}'

#%UU%
#%MDESC%
#   Stop once the current command is completed 
#
def marstop '{
   tty_cntl("md")
   print "   <MAR345> - Wait now the scanner ends. "
   print "           Don\'t hit Ctrl-C, please."
   tty_cntl("me")
   mar_wait()
}'


#%IU%
#%MDESC% 
#   sub-macro to be chained with cleanup_once
#
def mar_cleanup '{
  marstop
}'

#%IU%
#%MDESC%
def mar_prompt '{
   cdef("","","mar_cleanup","delete")
}'                                   

#%IU%
#%MDESC% 
#   sub-macro calls by the marscan and marcollect macros
#
def _marscan '{

  camera_online

  # chain a cleanup macro
  cdef ("cleanup_once","mar_cleanup\n", "_mar_")

  if (!MAR_COLLECT)
     printf("   <MAR345> Launching Scan\r")

  MAR_CMDID = "SCAN"
  if (esrf_io(MAR_DEV, "DevScannerScan") != -1) {
    mar_wait()
    # now display the image with bining of 5
    # have to wait the server has really received all the data from the
    # the scanner otherwise we get a blank hole in the middle of the image
    # 
    sleep(.5)
    marread 5
  }
}'

#%UU%
#%MDESC%
# to get synchronized with the scanner
#
def marwait '{
  mar_wait()
}'

#%UU% ["mode"]
#%MDESC%
# change the mode
#
def marmode '{
   local modes _mode i bad
 
   modes[0] = 2300
   modes[1] = 2000
   modes[2] = 1600
   modes[3] = 1200
   modes[4] = 3450
   modes[5] = 3000
   modes[6] = 2400
   modes[7] = 1800

   if (MAR_DISABLED) { 
     print "   <MAR345> Disabled. Command ignored."
   }else{

     bad = 1 
     if ( $# == 1 ) { 
       for ( i = 0;i < 8 ; i++) {
          if ( $1 == modes[i] ) {
              _mode = i
              bad = 0
              break
          }
       } 
     }

     if (bad) {
        printf ("Usage: marmode mode\n")
        printf ("     Mode in: ") 
        for (i=0;i<8;i++) printf("/ %d ",modes[i]) 
        printf ("\n")
     }else {
       MAR_CMDID = "CHANGE MODE"
       if (esrf_io(MAR_DEV,"DevScannerSetMode", $1) == -1) exit
       # chain a cleanup macro
       cdef ("cleanup_once","mar_cleanup\n ", "_mar_")
       mar_wait()
     }
   }  
}'

#%UU% ["format"]
#%MDESC%
#   Change the format
def marformat ' {

  if ($#!=1 && "$1" != "image" && "$1" != "mar") {
      print "Usage: marformat < MAR345 | IMAGE | SPIRAL >"
      exit
  }

  if (MAR_DISABLED) { 
     print "   <MAR345> Disabled. Command ignored."
  }else {
    MAR_CMDID = "FORMAT"
    MAR_FORMAT = "$1"
    if (esrf_io(MAR_DEV, "DevScannerSetFormat", MAR_FORMAT) == -1) exit
    mar_wait()
  }
}'

#%UU%
#%MDESC%
#   Start erasure of the image plate, take a while ...
#
def marerase '{

  if (MAR_DISABLED) { 
     print "   <MAR345> Disabled. Command ignored."
  } else {
    MAR_CMDID = "ERASE"
    # chain a cleanup macro
    cdef ("cleanup_once","mar_cleanup\n", "_mar_")
    if (esrf_io(MAR_DEV, "DevScannerErase")!=-1) {
      mar_wait()
    }
  }
}'

#%UU%
#%MDESC%
#
# Set new file parameters. 
#
def marnewfile '{

 print "Please enter:"
 MAR_N   = getval("   - Image number:     ",MAR_N)
 MAR_IMAGEDIR   = getval("   - Data directory on the MAR computer:   ",MAR_IMAGEDIR) 
 MAR_PREFIX     = getval("   - Prefix for files: ",MAR_PREFIX)
 MAR_OVRW       =  yesno("   - Overwrite existing file: (y/n)", MAR_OVRW)
 mar_filepar()
}'

#%UU%
#%MDESC%
#
# Set image parameters, detector distance and wavelength
#
def marimagepar '{

 print "Please enter:"
 MAR_DIST   = getval("   - Detector Distance (mm): ",MAR_DIST)
 MAR_WAV    = getval("   -  Wavelength (A):        ",MAR_WAV) 
 mar_imagepar()
}'

def mar_imagepar() '{
  local mar_impar
  mar_impar = sprintf("opt_distance=%f opt_wavelength=%f", MAR_DIST, MAR_WAV)
  return esrf_io(MAR_DEV, "DevScannerSetOptPar", mar_impar)
}'

#%IU%
#%MDESC%
#
# internal function that really set the new file parameters. 
# return -1 if the esrf_io failed
def mar_filepar() '{

  local mar_par
  
  mar_par[0] = MAR_IMAGEDIR
  mar_par[1] = MAR_PREFIX
  mar_par[2] = sprintf("%d",MAR_N)
  mar_par[3] = "%03d"
  mar_par[4] = (MAR_OVRW)?"y":"n"

  return esrf_io(MAR_DEV, "DevScannerSetFilePar", mar_par)
}'

#%IU%
#%MDESC%
#
# internal function that reset the current filename setting 
# return -1 if the esrf_io failed
def mar_getfilename() '{

  local mar_par
  local mar_format
  local mar_mode

  mar_par[0] = MAR_IMAGEDIR
  mar_par[1] = MAR_PREFIX
  mar_par[2] = sprintf("%d",MAR_N)
  mar_par[3] = "%03d"
  mar_par[4] = (MAR_OVRW)?"y":"n"

  if (esrf_io(MAR_DEV, "DevScannerGetFilePar", mar_par)==-1) return -1
  if ((mar_mode=esrf_io(MAR_DEV, "DevScannerGetMode"))==-1) return -1
  if ((mar_format=esrf_io(MAR_DEV, "DevScannerGetFormat"))==-1) return -1

  MAR_N = mar_par[0]
  MAR_PREFIX = mar_par[1]
  sscanf(mar_par[2],"%d",MAR_N)
  MAR_OVRW = (mar_par[4]=="Y")?1:0
  MAR_SUFFIX = (mar_format==0)? "mar":((mar_format==1)? "image": "s")
  if (mar_format == 0) MAR_SUFFIX = sprintf("%s%d", MAR_SUFFIX, mar_mode)

  return sprintf("%s/%s%03d.%s", MAR_IMAGEDIR, MAR_PREFIX, MAR_N, MAR_SUFFIX)
}'


#%IU%
#%MDESC%
#   Check for termintaion of command. 
#
def mar_wait() '{ 

  while (esrf_io(MAR_DEV, "DevState") == 14) {
     printf("   <MAR345> Command (%s) %d %% complete                  \r", MAR_CMDID, esrf_io(MAR_DEV,"DevScannerProgress"))
      sleep(.5)
   }  # end while
}'   

def marshow '{
    printf("\n\n<MAR345> Collect Settings   ____________\n\n")
    printf("  Filename prefix:               %s\n", MAR_FILEPREFIX)
    printf("  Number of Frames:              %d\n", MAR_NOIMGS)
    printf("  Number of Passes:              %d\n", MAR_NOPASSES)
    printf("  Rotation Oscillation (degree): %f\n", MAR_OSCILLATION)
    printf("  Oscillation overlap (degree):  %f\n", MAR_OVERLAP)
    printf("  Exposure time per pass(s):     %f\n", MAR_EXPOSTIME)
    printf("  Starting Angle (degree):       %f\n", MAR_STARTANGLE)
    printf("  Data Directory:                %s\n", MAR_IMAGEDIR)
    printf("  Overwrite existing file:       %s\n", MAR_OVRW?"Yes":"No")
    printf("  Erase:                         %s\n", MAR_ERASE?"Yes":"No")
    printf("________________________________________\n\n")
}'

def mar_getvals '{
    MAR_FILEPREFIX    = getval("  * Filename prefix:       ", MAR_FILEPREFIX)
    MAR_NOIMGS        = getval("  * Number of Frames:      ", MAR_NOIMGS)
    MAR_NOPASSES      = getval("  * Number of Passes:      ", MAR_NOPASSES)
    MAR_OSCILLATION   = getval("  * Rotation Oscillation (degree): ", \
                                  MAR_OSCILLATION)
    MAR_OVERLAP       = getval("  * Oscillation overlap (degree):  ", \
                                  MAR_OVERLAP)
    MAR_EXPOSTIME     = getval("  * Exposure time (s):             ", \
                                  MAR_EXPOSTIME)
    MAR_STARTANGLE    = getval("  * Starting Angle (degree):       ", \
                                  MAR_STARTANGLE )
    MAR_IMAGEDIR      = getval("  * Data Directory:                ", \
                                  MAR_IMAGEDIR)
    MAR_OVRW          = yesno("  * Overwrite existing file :       ", \
				  MAR_OVRW)
    MAR_ERASE         = yesno("  * Erase data after scan :         ", \
				  MAR_ERASE)
}'

#%UU% ["filename prefix"] ["frames number"] ["passes number"] ["oscillation range"] ["oscillation overlap"] ["exposure time"] ["starting position"] ["image directory"] ["erase first"]

#%MDESC%
#     Performs the data collection. will acquire [frames number] images
#     into the ["image directory"] directory with the file names 
#     ["filename prefix"]_$$ (where $$ is from [starting frame number]
#     to [starting frame number]+[frames number]. The first position
#     will be [starting position], the angle oscillation for each frame
#     is [oscillation range] and there will be [passes number] passes for
#     each frame in [exposure time] seconds.
def marcollect '{
    global MAR_NOIMGS MAR_NOPASSES MAR_ERASE
    global MAR_OSCILLATION MAR_OVERLAP MAR_EXPOSTIME
    global MAR_STARTANGLE

    MAR_COLLECT = 1


    if ($#) {
        MAR_FILEPREFIX    = "$1"
        MAR_NOIMGS        =  $2
        MAR_NOPASSES      =  $3
        MAR_OSCILLATION   =  $4
        MAR_OVERLAP       =  $5
        MAR_EXPOSTIME     =  $6
        MAR_STARTANGLE    =  $7
        MAR_IMAGEDIR      = "$8"
        MAR_OVRW          = "$9"
        MAR_ERASE         = "$10"
    } else {
        inloop = 1
	while(inloop) {
	    marshow
	    _yn=yesno("Do you want to change these settings",0)
	    if (_yn) {
	       mar_getvals
            } else {
               inloop = 0
            }
        }
    }

    if (MAR_NOPASSES == 0) {
	 MAR_NOPASSES = 1
    }

    MAR_N = 0   # always 0

    MAR_PREFIX = sprintf("%s_%03d_",MAR_FILEPREFIX,SCAN_N+1)

    #
    # Test if the file parameters are valid
    #
#    MAR_DATADIR     = sprintf("%s/%s",MARHOME,MAR_IMAGEDIR)

    if (mar_filepar() == -1 ) {
       printf("   <MAR345> Invalid parameters\n")
       exit
    }

    HEADING = "marcollect " MAR_FILEPREFIX " " MAR_NOIMGS " " MAR_NOPASSES  
    HEADING = HEADING " " MAR_OSCILLATION " " MAR_OVERLAP " " MAR_EXPOSTIME
    HEADING = HEADING " " MAR_STARTANGLE " " MAR_IMAGEDIR " " MAR_ERASE

    mname = motor_name(motor_num(PHI_MOTOR_NAME))
    FPRNT=sprintf("Frame_no  %s  ",mname)
    VPRNT=sprintf("%9.9s ",mname)

    scan_head

    mar_loop_frames() 
    cdef("","","_phiosc_","delete")
}'

def mar_head '{
     HEADING="marcollect $*"
     scan_head
}'

#%IU%
#%MDESC%
#
def mar_loop_frames() '{

 local curr_frame curr_pass start_angle stop_angle expo_time
 
 curr_frame = 0
 curr_pass = 0

 while ( curr_frame < MAR_NOIMGS) {

     if (MAR_ERASE) {
         marerase
     }

     start_angle = MAR_STARTANGLE + (curr_frame * (MAR_OSCILLATION-MAR_OVERLAP))
     stop_angle  = start_angle + MAR_OSCILLATION 
     expo_time   = MAR_EXPOSTIME

     waitmove; get_angles

     VFMT="%3.4f "
     FPRNT=sprintf("%.8g ",start_angle)
     VPRNT=sprintf(VFMT,start_angle)

     tty_cntl("md")
     sp = sprintf("      Frame % 3d: ", MAR_N)
     tty_cntl("me")
     sp = sp sprintf("%3.2f -> %3.2f ",start_angle,stop_angle) 

     #
     # While statement to make the passes for each frame
     #
     curr_pass = 0

     for ( i = 0;i<COUNTERS;i++) {
         MAR_CNT[i] = 0
     }


     while (curr_pass < MAR_NOPASSES) {
          tty_cntl("md")
          printf("%s => Pass %d       \r", sp,curr_pass+1)
          tty_cntl("me")

          phi_oscillation start_angle stop_angle expo_time
 
          curr_pass++

	  getcounts

          for ( i = 0;i<COUNTERS;i++) {
	      if (counter_par(0,"controller")  != "NONE")
                 MAR_CNT[i] += S[i]
              else		  
                 MAR_CNT[i] += S_saved[i]
          }
     } 

     for ( i = 0;i<COUNTERS;i++) {
        S[i] = MAR_CNT[i] 
     }

     cdef("","","_phiosc_","delete")
  
     _marscan

     MAR_N++; curr_frame ++
     mar_dataloop
  }
}'

def mar_dataloop '{
     local n

     n = int((COLS - length(VPRNT) - length(Pout) - 24) / 9)

     s = sprintf("%3d %s%g ", NPTS,VPRNT,S[DET])

     NPTS++

     if (MON >= 0) {
          s = s sprintf("%g ", S[MON])
          n--
     }

     s = s sprintf("%10.6g ",S[sec])

     for (i=0; i<COUNTERS && n>0; i++) {
         if (i!=DET && i !=MON && i!=sec && is_using_counter(i)) {
              s = s sprintf("%8.4g ", S[i])
              n--
         }
     }

     printf("%s%s\n",s,Pout)

     if (DATAFILE != "") {
          fprintf(DATAFILE,"%d %s%s%d",NPTS,FPRNT,Fout,(TIME_END=time())-EPOCH)
          for (i=0;i<COUNTERS;i++)
                if (i != MON && i != DET && is_using_counter(i))
                       fprintf(DATAFILE," %g",S[i])
          fprintf(DATAFILE," %g",S[MON])
          fprintf(DATAFILE," %g\n",S[DET]);
     }

}'

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# The file(s) mar345.mac, ccd.mac have to be read in
#%AUTHOR% L.Claustre / V.Rey, 1997-2002
#$Revision: 2.4 $ 
#%TOC%