esrf

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

#%TITLE% MSCAN.MAC
#%NAME%
# Macro for special mirror scans to determine its shape
#
#%CATEGORY% Scans
#
#%DESCRIPTION%
# The incoming beam will be scanned in height and at each point the
# outgoing reflection will be searched with another scan.
# You will need a motor which can scan the beam up and down ( a
# pinhole for example) and a motor which scans a one dimensional
# detector up and down (like a wire monitor or a slit).
# The resulting data can be treated with a special program (contact us)
#

#%UU%
#%MDESC%
# Sets the scan up. the following questions will be asked:
# %DL%
# %DT% Factor to multiply FWHM to get new scan width %DD%
#  After the first wire scan, the new scan will be done around the 
#  the point where the beam should be for a plane mirror.
# %DT% Minimum FWHM to accept a peak as a peak %DD%
# %DT% Minimum max_counts to accept peak %DD%
#  Both questions are to define the beam on the wire monitor
# %DT% Distance Mirror-zero to wire monitor [m] %DD%
# %DT% Mirror Angle (for Slope Error) [mrad] %DD%
#  Questions about the geometrical setup of your experiment
# %DT% Do you want to do a regular check scan %DD%
#  A regular checkscan with the beam going back to 0 and a wire scan
#  can be done to be sure not to loose steps. All the following
#  questions are for these checkscans
#
# %DT% Interval between check scans (1,2,..)  %DD%
# %DT% From Position %DD%
# %DT% To Position %DD%
# %DT% No of points %DD%
# %DT% Count time %DD%
# %XDL%

def mscansetup '
  global MSC_FACTOR MSC_MINCOUNTS MSC_MINFWHM MSC_Q MSC_TH
  global MSC_GRPRES MSC_GRPMEA MSC_RESNO MSC_MEANO
  global MSC_CHECK MSC_CSTART MSC_CEND MSC_NOPTS MSC_CTIME
  global MSC_INPUT
  MSC_GRPRES = 46
  MSC_GRPMEA = 47
  data_grp(MSC_GRPRES,4096,3)
  data_grp(MSC_GRPMEA,4096,4)
  MSC_FACTOR=getval("Factor to multiply FWHM to get new scan width",MSC_FACTOR)
  MSC_MINFWHM = getval ("Minimum FWHM to accept a peak as a peak",MSC_MINFWHM)
  MSC_MINCOUNTS = getval("Minimum max_counts to accept peak",MSC_MINCOUNTS)  
  MSC_Q = getval("Distance Mirror-zero to wire monitor [m]",MSC_Q) 
  MSC_TH = getval("Mirror Angle (for Slope Error) [mrad]",MSC_TH)    
  if (MSC_CHECK = yesno("Do you want to do a regular check scan",MSC_CHECK)){
    MSC_FRQ = getval("Interval between check scans (1,2,..) ",MSC_FRQ)
    MSC_CSTART = getval("From Position",MSC_CSTART)    
    MSC_CEND = getval("To Position",MSC_CEND)    
    MSC_NOPTS = getval("No of points",MSC_NOPTS)    
    MSC_CTIME = getval("Count time",MSC_CTIME)    
    }

'

#%UU% <mot1 s1 f1 intervals1  mot2 s2 f2 intervals2  time>
#%MDESC%
# Derived from a standard spec mesh scan. The mot1 will be the wire
# (or beam monitor) and mot2 the pinhole (beam scan motor)
#
#
def mscan '
        global MSC_FSTART MSC_SSTART
        global MSC_FSTART2 MSC_SSTART2
	if ($# != 9) {
		print \
	    "Usage:  mscan  mot1 s1 f1 intervals1  mot2 s2 f2 intervals2  time"
		exit
	} 
	MSC_INPUT="$0"
        _check0 "$1"; _check0 "$5"
	{
		_m[0] = $1; _s1 = $2; _f1 = $3; _n1 = int($4)
		_m[1] = $5; _s2 = $6; _f2 = $7; _n2 = int($8)
		_ctime = $9
	}
	if (_n1 <= 0 || _n2 <= 0) {
		print "Intervals <= 0"
		exit
	} 
	
	_bad_lim = 0
	_chk_lim _m[0] _s1
	_chk_lim _m[0] _f1
	_chk_lim _m[1] _s2
	_chk_lim _m[1] _f2
	if (_bad_lim) exit
	
	MSC_FSTART = _f1 ; MSC_SSTART = _s1 ; 
	MSC_FSTART2 = _f2 ; MSC_SSTART2 = _s2 ; 
        MSC_RESNO = 0 ; MSC_MEANO = 0
	HEADING = sprintf("mscan  $1 %g%s %g%s %g  $5 %g%s %g%s %g  %g",\
		       ($2)*UN,UL, ($3)*UN,UL, $4, ($6)*UN,UL, ($7)*UN,UL, $8, $9)

	_d1 = (_f1 - _s1) / _n1++; _d2 = (_f2 - _s2) / _n2++
	_nm=2
	_cols=2+_hkl_col
	X_L = "$1"; _sx = _s1*UN; _fx = _f1*UN
	Y_L = cnt_name(DET)
	_stype = 1|8|(2<<8)
	FPRNT=sprintf("%s  %s  ",motor_name(_m[0]),motor_name(_m[1]))
	PPRNT=sprintf("%8.8s %8.8s ",motor_name(_m[0]),motor_name(_m[1]))
	VPRNT=sprintf("%9.9s %9.9s ",motor_name(_m[0]),motor_name(_m[1]))
	FPRNT=sprintf("%s%s  ",FPRNT,_hkl_sym1)
	scan_head
	PFMT=sprintf("%%8.%df %%8.%df ",UP,UP)
	VFMT=sprintf("%%9.%df %%9.%df ",UP,UP)
	_g2 = 0
	_g1 = _n1
	def _scan_on \'
	 for (; _g2 < _n2; _g2++){
		msc_checksteps
		A[_m[1]] = _s2 + _g2 * _d2
	        if (_g1 == _n1) {
   	 	  _g1 = 0;
		  NPTS=0
		}
 		for (; _g1 < _n1; _g1++, NPTS++) {
			A[_m[0]] = _s1 + _g1 * _d1
			scan_move
			FPRNT=sprintf("%g %g ",A[_m[0]]*UN,A[_m[1]]*UN)
			PPRNT=sprintf(PFMT,A[_m[0]]*UN,A[_m[1]]*UN)
			VPRNT=sprintf(VFMT,A[_m[0]]*UN,A[_m[1]]*UN)
			FPRNT=sprintf("%s%s ",FPRNT,_hkl_val)
			scan_loop
			data_nput(PL_G,_g1,A[_m[0]]*UN, S[DET])
			scan_plot
		}
		msc_calcpars
	  }
	  scan_tail
          msc_calcres
          mscslope
	\'
	_scan_on
'

def msc_calcpars '
  {
    mfwhm = msc_FWHM ; cfwhm = msc_CFWHM ; mmax  = msc_MAX
    data_nput(MSC_GRPMEA,MSC_MEANO++,_s2+_g2*_d2,cfwhm,mfwhm,MSC_CHECKPOS) 
    mfwhm = (mfwhm < MSC_MINFWHM) ? MSC_MINFWHM : mfwhm
    if (mmax < MSC_MINCOUNTS) {
      _s1 = MSC_SSTART
      _f1 = MSC_FSTART
    } else {
      _s1 = cfwhm - MSC_FACTOR/2*mfwhm- _d2 
      _f1 = cfwhm + MSC_FACTOR/2*mfwhm- _d2
      _s1 = (_s1< MSC_SSTART) ? MSC_SSTART : _s1
      _f1 = (_f1> MSC_FSTART) ? MSC_FSTART : _f1
      msc_res    
    }  
    _n1 = int((_f1-_s1)/_d1+1)
    _g1 = _n1
  } '


def msc_res '
  #Calc profile and deviat.
  offset = (_s2+_d2*_g2)
  xideal = MSC_Q*1000*sin(2*MSC_TH/1000) - offset
  xshift = cfwhm - xideal 
  slope = xshift / (MSC_Q-offset/sin(2*MSC_TH/1000)) * 1000 
  mpos = offset / sin(MSC_TH/1000)
  data_nput(MSC_GRPRES,MSC_RESNO++,mpos,slope)
  '  


def msc_calcres '
  # Calc integral
  {
  data_put(MSC_GRPRES,0,2,0)
  for (uu=1,integral = 0;uu<MSC_RESNO;uu++) {
    integral += (data_get(MSC_GRPRES,uu-1,1)+data_get(MSC_GRPRES,uu,1))/2
    data_put(MSC_GRPRES,uu,2,integral)
    }
  }
  '

def mscslope '
  Y_L = "slope";  X_L = "Mirror position [mm]"
  plot_cntl("filter2")
  plot_cntl("-ylog")
  plot_cntl("dots")
  plot_cntl("lines")
  plot_cntl("-ebars")
  splot MSC_GRPRES 0 1
  plot_cntl("filter1")
'

def mscpos '
  Y_L = "Position [um]";  X_L = "Mirror position [mm]"
  plot_cntl("-ylog")
  plot_cntl("dots")
  plot_cntl("lines")
  plot_cntl("-ebars")
  splot MSC_GRPRES 0 2
'

def msc_checksteps '
{
  if (MSC_CHECK && (MSC_TURN == 0)) {
    local uu _dd
    A[_m[1]] = s2+0;
    _dd = (MSC_CSTART - MSC_CEND) / MSC_NOPTS; 
    for (uu=0;uu<MSC_NOPTS+1;uu++) {
      A[_m[0]] = MSC_CSTART + uu * _dd
      scan_move
      scan_count (MSC_CTIME)
      data_nput(PL_G,uu,A[_m[0]]*UN, S[DET])      
    }
    MSC_CHECKPOS= msc_CFWHM
  } else {
    MSC_CHECKPOS=0
  }
  if (++MSC_TURN >= MSC_FRQ) MSC_TURN=0 
}'


#%UU% 
#%MDESC%
# Print the results from the last scan on the screen
#
def mscshow '
{
  local i
  printf("#C Date: %s  User: %s  Version: %s\n",date(),USER,SPEC)
  printf("#C Command: mscan %s\n",MSC_INPUT)
  printf("#C Factor: %f Min FWHM: %f Min Counts: %f Distance %f [m] Theta %f [mrad]\n",MSC_FACTOR ,MSC_MINFWHM,MSC_MINCOUNTS,MSC_Q,MSC_TH)
  if (MSC_CHECK) {
  printf ("#C Check Scan: Freq. %d Start: %f End: %f Pts: %f Time:%f\n",\
    MSC_FRQ,MSC_CSTART,MSC_CEND,MSC_NOPTS,MSC_CTIME)
  }
  printf("#C Measured Values:\n")
  printf("%3s %10s %10s %10s %10s \n","No","Slit","Wire-Center","FWHM","Check Pos")
  for (i=0;i<MSC_MEANO;i++) {
    printf("%3d %10f %10f %10f %10f\n",i+1,data_get(MSC_GRPMEA,i,0),data_get(MSC_GRPMEA,i,1), data_get(MSC_GRPMEA,i,2),data_get(MSC_GRPMEA,i,3))
  }
  printf("#C Calulated Mirror Position (Approximation)\n")
  printf("%3s %10s %10s %10s\n","No","M-Pos","Slope","Integral")
  for (i=0;i<MSC_RESNO;i++) {
    printf("%3d %10f %10f %10f \n",i+1,data_get(MSC_GRPRES,i,0),data_get(MSC_GRPRES,i,1), data_get(MSC_GRPRES,i,2))
  }

}'

def msc_MAX 'data_anal(PL_G,0,0,   0,PL_Y,"max")'
def msc_FWHM 'data_anal(PL_G,0,0,   0,PL_Y,"fwhm")'
def msc_CFWHM 'data_anal(PL_G,0,0,   0,PL_Y,"cfwhm")'


#%MACROS%
#%IMACROS%
#%AUTHOR% JK
#%TOC%