#%TITLE% TURBOSCAN.MAC
#%NAME%
# Turbo scan macros
#%DESCRIPTION%
# This macro cntset uses a scan server allowing simultaneous
# multiple read (encoders and vct6 channels at the same time).%BR%
#%BR%
# With minimum network load, fastest read time is around 40 msec.%BR%
#%BR%
#%XDL%
#%SETUP%
#%UL%%B%turbosetup%B% [<Scanserv-devname> <0|1> <Vct6-devname>] %BR%
# First parameters is scan server device name. %BR%
# Second parameter is nevether you want to save or not (1=save). %BR%
# Third parameter is vct6 device name. %BR%
# Fourth parameter has to be set to 1 until program advises to change it.%BR%
#%BR%
#
#%OVERVIEW%
# The following macros are provided:
#%DL%
#%DT%turboscan%DD% one motor continuous scan.%BR%
#%DT%turboscan2%DD% two motors continuous scan. %BR%
#%DT%turbosplot%DD% turboscan special splot. %BR%
#%BR%
#
#%EXAMPLE%
#%DL%
#%DT% turboscan om 0 1 1 50 %BR%
# this will scan at 1deg/s speed between position 0 and 1 %BR%
# with a readcnt every 50 msec %BR%
#%DT% turboscan2 om 0 1 2 theta 5 9 60 %BR%
# motor om drives from 0 to 1 at 2 deg/min %BR%
# theta goes at the same time from 5 to 9. %BR%
# theta's speed is adapted for that the 2 motors reach %BR%
# their final point together %BR%
# reads are performed every 60 msec %BR%
#
#%END%
#%X%
#%UU% [<Scanserv-devname> <0|1> <Vct6-devname> <Sleep-time>]
#%MDESC%
#
def turbosetup '{
local i
constant TS_TIMEMIN 100
constant TS_SECURITY 9096 # on bm16; 2048 on id12
global TS_SETUPCHECK TS_SAVE
global TS_TIME TS_SPEED TS_REALTIME TS_REALSPEED TS_MAXTIME
global TS_VELO TS_OLDVELO TS_OLDBASE TS_OLDACC
global TS_DEVNAME TS_VCT6SERV TS_NBCHA TS_MASTER TS_ELEM TS_NBREAD
global TS_FIRST
global TS_NPTS TS_IDX
global TS_SLEEP TS_ONEMOTOR TS_ONEMNE
global TS_FPRNT # used in _turbo_save_point
TS_TIME = TS_TIMEMIN
TS_MAXTIME = pow(2,31) / counter_par(sec,"scale") # vct6 is 32 bit counter
TS_SETUPCHECK = 1
TS_MASTER = (counter_par(sec,"unit")+1) * 100 + counter_par(sec,"channel")
# I need here one mnemonic of one of the motors to scan. Otherwise we have
# all kind of errors in cntconfig. This is used in ts_cntconfig.
if ($#) {
TS_DEVNAME = "$1"
TS_VCT6SERV = "$2"
TS_SLEEP = $3
TS_NBCHA = $4
TS_ONEMNE = $5
} else {
TS_DEVNAME = getval("Scan server device name",TS_DEVNAME)
TS_VCT6SERV = getval("Vct6 device name (ie D16/VCT6_1)",TS_VCT6SERV)
TS_SLEEP = getval("Time interval SPEC reads from VME buffer",\
TS_SLEEP ? TS_SLEEP : 1)
TS_NBCHA = getval("How many Vct6 channel",TS_NBCHA )
TS_ONEMNE = getval("Enter the mnemonic of one posible motor to scan",TS_ONEMNE )
}
# TS_NBREAD = int (4096 / (2 + 2*TS_NBCHA + 2)) # Maximum 2 motors (last +2)
# Now it could be more, 4096
# was limit for data_group
TS_NBREAD=2048
if (motor_num(TS_ONEMNE) != -1)
TS_ONEMOTOR = motor_par(motor_num(TS_ONEMNE),"channel")+1
else
p "Warning, motor mne not defined:",TS_ONEMNE
cdef("config_mac","_turbo_oldspeed ; _turbo_cntconfig; ","turbo")
_turbo_oldspeed
_turbo_cntconfig
}'
#%UU% <motor mne> <from> <to> <deg/min> [ms read]
#%MDESC% one motor continuous scan.
#
def turboscan '{
if (!TS_SETUPCHECK) { print "Error: run turbosetup first."; exit }
if (($# != 4) && ($# != 5)) {
p "Usage: $0 <motor mne> <from> <to> <deg/min> [ms read]"
exit
} else {
_m[0]=motor_num("$1"); _s[0]=$2; _f[0]=$3; TS_SPEED[0]=$4; _nm = 1
if ($5) {
TS_TIME=$5
} else {
TS_TIME=TS_TIMEMIN
}
}
cdef("user_cleanup2","_turbo_cleanup; ", "turbo")
HEADING = sprintf("turboscan $*")
# GBMV Put the date here, took it out of turboscan...
DATE = date()
_turbo_check
_turbo_init
_turbo_prepfprintf
_turboscan
}'
#%UU% <motor1> <from> <to> <deg/min> <motor2> <from> <to> [ms read]
#%MDESC% two motor continuous scan
#
def turboscan2 '{
if (!TS_SETUPCHECK) { print "Error: run turbosetup first."; exit }
if (($# != 7) && ($# != 8)) {
p "Usage: $0 <mot1> <from> <to> <deg/min> <mot2> <from> <to> [ms read]"
p " speed for motor2 is calculated by the macro"
exit
} else {
_m[0]=motor_num("$1"); _s[0]=$2; _f[0]=$3; TS_SPEED[0]=$4;
_m[1]=motor_num("$5"); _s[1]=$6; _f[1]=$7; _nm = 2
if ($8) {
TS_TIME=$8
} else {
TS_TIME=TS_TIMEMIN
}
}
cdef("user_cleanup2","_turbo_cleanup; ", "turbo")
HEADING = sprintf("turboscan2 $*")
# GBMV put it here
DATE = date()
_turbo_check
_turbo_init
_turbo_prepfprintf
_turboscan
}'
#%IU%
#%MDESC% Parameter check for the macros %B%turbo%B%
#
def _turbo_check '{
local mot
for (mot = 0; mot < _nm; mot ++) {
if (_m[0] == -1) {
p "Invalid motor name"
exit
}
_bad_lim = 0
_chk_lim _m[mot] _s[mot]
_chk_lim _m[mot] _f[mot]
if (_bad_lim) exit
}
}'
#%IU%
#%MDESC% Initialisations for the macros %B%turbo%B%
#
def _turbo_init '{
local mot_list i_mot
# GBMV
local mot_command
mot_list = motor_mne(_m[0])
for (i_mot = 1; i_mot < _nm; i_mot++) {
mot_list = sprintf("%s, %s", mot_list, motor_mne(_m[i_mot]))
}
printf("Moving %s to the start position..\n", mot_list)
# GBMV thinks update1 + 2 need now motor mne instead of number or something
# just do this:
for (i_mot = 0; i_mot < _nm; i_mot++) {
A[_m[i_mot]] = _s[i_mot]
mot_command = sprintf("%s %s %f", \
mot_command, motor_mne(_m[i_mot]), A[_m[i_mot]] )
}
_mmv(0x02, mot_command, A[_m[0]] )
#insted of this:
# waitmove; get_angles;
# for (i_mot = 0; i_mot < _nm; i_mot++) {
# A[_m[i_mot]] = _s[i_mot]
# }
# move_em ;
# if (_nm == 1) {
# _update1 _m[0]
# } else {
# _update2 _m[0] _m[1]
# }
_turbo_set_speed
_turbo_init_group
_turbo_save_header
turborplot
}'
#%IU%
#%MDESC% Saves the old speed for the continuous scan.
#
def _turbo_oldspeed '{
local i_mot
for (i_mot = 0; i_mot < _nm; i_mot++) {
TS_OLDVELO[i_mot] = motor_par(_m[i_mot],"velocity")
TS_OLDBASE[i_mot] = motor_par(_m[i_mot],"base_rate")
TS_OLDACC[i_mot] = motor_par(_m[i_mot],"acceleration")
}
}'
#%IU%
#%MDESC% Sets the new speed for the continuous scan.
#
def _turbo_set_speed '{
local i_mot
if (_s[0] != _f[0])
TS_SPEED[1]=fabs(_s[1]-_f[1]) / fabs(_s[0]-_f[0]) * TS_SPEED[0]
for (mm=0; mm < _nm; mm++) {
TS_VELO[mm] = TS_SPEED[mm] * fabs(motor_par(_m[mm],"step_size")) / 60
motor_par(_m[mm],"velocity",TS_VELO[mm])
if (motor_par(_m[mm],"base_rate") > TS_VELO[mm])
motor_par(_m[mm],"base_rate",TS_VELO[mm]/2)
motor_par(_m[mm],"get_pars")
if (motor_par(_m[mm],"base_rate") > TS_VELO[mm])
p "Warning: Base rate is: ",motor_par(_m[mm],"base_rate"),"steps/s"
TS_REALSPEED[mm] = fabs(60 * motor_par(_m[mm],"velocity") \
/ motor_par(_m[mm],"step_size"))
printf("Motor %s will drive at %7.4f deg/min \n",motor_mne(_m[mm]), \
TS_REALSPEED[mm])
}
if (TS_REALSPEED[0])
TS_REALTIME = fabs((_f[0]-_s[0]) / TS_REALSPEED[0] * 60)
}'
#%IU%
#%MDESC%
#
def _turbo_init_group '{
local ts_size esttime
TS_ELEM = 1 + TS_NBCHA*2 + _nm
if ((esttime = int (TS_TIME/10) - 1) == 0)
esttime = 1
TS_SIZE = TS_REALTIME/esttime*100 + TS_SECURITY
array TS_ARRAY[TS_SIZE][1+TS_NBCHA+_nm]
array TS_ARRBUFF[TS_NBREAD][TS_ELEM]
array TS_LASTPT[1][100]
}'
#%IU%
#%MDESC%
#
def _turboscan '{
local ts_units ts_label ts_readval ts_line ts_cnt ts_runpars i j k
local ts_sleept ts_stime ts_stop
if (TS_REALTIME > 60) { ts_units = 60; ts_label="min." }
else if (TS_REALTIME > 1) { ts_units = 1; ts_label="sec." }
else { ts_units = 0.001; ts_label="msec." }
printf("Get ready for scan %d of %10.2f %s\n",SCAN_N,\
TS_REALTIME/ts_units, ts_label)
ts_stop = 0
# GBMV commented this out and put it in turbo_scan to hopefully correct
# previous scan date thing
# DATE = date()
_ctime = TS_TIME
T_L = "Scan" SCAN_N
X_L = motor_name(_m[0])
Y_L = cnt_name(DET)
esrf_io(TS_DEVNAME,"tcp")
ts_runpars[0] = TS_TIME
ts_runpars[1] = TS_MASTER
for (k=0; k<_nm;k++) {
ts_runpars[2+k] = motor_par(_m[k],"channel")+1
}
ts_cnt = 0
get_angles
for (i = 0; i < _nm; i++) {
A[_m[i]] = _f[i]
}
count_em TS_MAXTIME
esrf_io(TS_DEVNAME,"DevRun",ts_runpars)
sleep(1)
esrf_io(TS_DEVNAME,"DevReadValues",TS_NBREAD,TS_ARRBUFF)
move_em
TS_NPTS = 0
TS_FIRST = 1
TS_EPOCH = 0 # or use time() think later
while (chk_move) {
ts_stime = time()
ts_readval = esrf_io(TS_DEVNAME,"DevReadValues",TS_NBREAD,TS_ARRBUFF)
if (ts_readval > 0) {
_turbo_fastfill (ts_readval/TS_ELEM, TS_ARRAY)
_turbo_fastsave (ts_readval/TS_ELEM)
plot_cntl("addpoint")
_turbo_ppoint
}
ts_sleept = TS_SLEEP - (time() - ts_stime)
if (ts_sleept > 0)
sleep (ts_sleept)
printf("\r%5d %s: %10.4f t: %10.4f", \
TS_ARRAY[TS_NPTS-1][0], motor_mne(_m[0]), \
TS_ARRAY[TS_NPTS-1][TS_NBCHA+1], TS_ARRAY[TS_NPTS-1][1] )
}
_turbo_end
if (TS_ARRAY[TS_NPTS-1][0] - TS_ARRAY[0][0] + 1 == TS_NPTS) {
p "Just worked great"
} else {
p " Lost a couple "
}
}'
#%IU%
#%MDESC% optimized version
#
def _turbo_fastfill(noval,arr) '{
local i n k ts_line val errors serrors thisval
global TS_LASTSEQ
for (i=0; i < noval; i++) {
val = TS_ARRBUFF[i][0]
if (!val) {
errors ++
continue
}
if (!TS_FIRST) {
if ( val <= TS_LASTSEQ) {
serrors++ # Sequence must be in order
continue
}
arr[TS_NPTS][0] = val # Seq. number
arr[TS_NPTS][1] = TS_ARRBUFF[i][2] / counter_par(sec,"scale") # epoch
if (arr[TS_NPTS][1] < arr[TS_NPTS - 1][1]) {
serrors++ #Negative time, strange
continue
}
for (k=2; k < TS_NBCHA+1; k++) { # Counters
arr[TS_NPTS][k] = TS_ARRBUFF[i][2*k] - TS_LASTPT[0][k]
TS_LASTPT[0][k] = TS_ARRBUFF[i][2*k]
}
for (k=0; k<_nm; k++) { # Motors
arr[TS_NPTS][TS_NBCHA+1+k] = TS_ARRBUFF[i][2*TS_NBCHA+1+k]\
/ motor_par(_m[k],"encoder_step_size")
}
TS_NPTS++
}
else {
TS_FIRST = 0
for (k=2; k < TS_NBCHA+1; k++) {
TS_LASTPT[0][k] = TS_ARRBUFF[i][2*k]
}
}
TS_LASTSEQ=val
}
if (errors)
printf ("\n%d wrong value(s) sent, try slower speed (now %d [ms])\n",\
errors,TS_TIME)
if (serrors) {
printf ("\n%d times points arrived out of order\n",serrors)
}
}'
#%IU%
#%MDESC%
#
def _turbo_cleanup '{
fprintf(DATAFILE, "# turboscan aborted with Ctrl-C\n")
_turbo_end
}'
#%IU%
#%MDESC%
#
def _turbo_end '{
local i_mot
stop(2)
p "Setting motor speed back .."
for (i_mot = 0; i_mot < _nm; i_mot++) {
motor_par(_m[i_mot],"velocity",TS_OLDVELO[i_mot])
motor_par(_m[i_mot],"base_rate",TS_OLDBASE[i_mot])
motor_par(_m[i_mot],"acceleration",TS_OLDACC[i_mot])
}
_turbo_stop
turbosplot
cdef("user_cleanup2","","turbo","delete")
}'
def _turbo_stop '
esrf_io(TS_DEVNAME,"DevStop")
'
#%IU%
#%MDESC% Called by _turbo_init
#
def _turbo_save_header '{
local i
FPRNT=""
for (i=0;i<_nm;i++) {
FPRNT=sprintf("%s%s ",FPRNT,motor_name(_m[i]))
}
FPRNT=sprintf("%s%s ",FPRNT,_hkl_sym1)
SCAN_N = savestdheader(DATAFILE,3,SCAN_N)
_cols= _nm+_hkl_col
offt; savecntheader(DATAFILE); ont;
}'
#%IU%
#%MDESC% Called in turbosetup and config_mac
# prepares macro _turbo_fprintf
#
def _turbo_prepfprintf '{
local i str1 str2 pos str3
str1 = ""
pos = $1
for (i=0; i<_nm; i++) {
# str1 = sprintf("%s %%.11g",str1)
# to remove the blank as first character
if (i == 0){
str1 = sprintf("%%.11g")
}
else {
str1 = sprintf("%s %%.11g",str1)
}
str2 = sprintf("%s,TS_ARRAY[pos][%d]",str2,TS_NBCHA+1+i)
}
str1 = sprintf("%s %s %s",str1,_hkl_val,Fout)
_turbo_prepfprintflocal1 sec
str1 = sprintf("%s %%g",str1)
str2 = sprintf("%s,val",str2)
for (i=0; i<COUNTERS; i++) {
if (i != sec && i != DET && i != MON && cnt_name(i) != "unused") {
_turbo_prepfprintflocal1 i
}
}
_turbo_prepfprintflocal1 MON
_turbo_prepfprintflocal1 DET
str3=sprintf("fprintf(file,\"%s\n\"%s)",str1,str2)
rdef _turbo_fprintf str3
}'
#%IU%
#%MDESC% reduces code size of _turbo_prepfprintf
# warning : uses local variable of _turbo_prepfprintf
#
def _turbo_prepfprintflocal1 '
if (TS_IDX[$1] != -1) {
str1 = sprintf("%s %%g",str1)
str2 = sprintf("%s,TS_ARRAY[pos][%d]",str2,TS_IDX[$1]+1)
}
else {
str1 = sprintf("%s %%g",str1)
str2 = sprintf("%s, S[%d]",str2,$1)
}
'
#%IU%
#%MDESC% Writes the scan data of one point to the data file.
# optimized version
#
def _turbo_fastsave(no_val) '{
local i n val pos file str
local array s[COUNTERS]
if (!(whatis("_turbo_fprintf")&2)) {
p "Error: _turbo_fprintf is not defined"
exit
}
file = DATAFILE
if (TS_NPTS && file != "" && file != "/dev/null") {
for (i=0; i<no_val; i++) {
if ((pos = TS_NPTS - no_val +i) < 0)
continue
ts_user_measure
if (pos) {
val = TS_ARRAY[pos][TS_IDX[sec]+1] - TS_ARRAY[pos-1][TS_IDX[sec]+1]
} else {
val = 0
}
_turbo_fprintf
}
close(DATAFILE)
}
}'
#%IU%
#%MDESC% Called by turbosetup
#
def _turbo_cntconfig '{
local ts_stateres i j ts_idx ts_idx2 ts_runpars ts_res
array readarr[1][30], ts_res[30]
ts_stateres[0]=0
ts_runpars[0] = 100
ts_runpars[1] = TS_MASTER
ts_runpars[2] = TS_ONEMOTOR
for (j=0; j<COUNTERS; j++) {
TS_IDX[j]=-1
}
esrf_io(TS_DEVNAME,"DevRun",ts_runpars)
sleep(1)
esrf_io(TS_DEVNAME,"DevReadValues",1,readarr)
esrf_io(TS_DEVNAME,"DevStop")
for (j=0; j<COUNTERS; j++) {
if (counter_par(j,"controller") == "VCT6") {
# I guess the Vct6 server name here.
sname = sprintf("%s/%d",TS_VCT6SERV, counter_par(j,"channel"))
esrf_io(sname,"DevCntState",ts_res)
ts_idx2 = ts_res[12] * 100 + ts_res[7]
for (i=0; i< TS_NBCHA; i++) {
ts_idx = readarr[0][2*i+1]
if (ts_idx == ts_idx2)
TS_IDX[j]=i
}
}
}
}'
#%UU%
#%MDESC% rplot (plot during acquisition) designed for turboscan
#
def turborplot '
plot_cntl("filter1")
plot_cntl("open")
plot_cntl(sprintf("colors=%s",rplot_col))
plot_move(0,1,T_L)
plot_move(0,2,Y_L)
plot_move(0,-1,sprintf("%.8s", X_L))
plot_cntl("title=TurboScan")
plot_cntl("erase")
plot_range(_s[0],_f[0],"auto","auto")
'
#%UU%
#%MDESC% splot designed for turboscan
#
def turbosplot '{
if (PLOT_MODE&128) {
plot_cntl(sprintf("colors=%s",splot_col))
plot_cntl("open")
}
plot_cntl("erase")
plot_range("auto","auto",YMIN,"auto")
plot_move(0,1,T_L)
plot_move(0,2,Y_L)
plot_move(0,-1,sprintf("%.8s", X_L))
_turbo_ppoint
plot_move(0,3)
}'
#%IU%
#%MDESC% Called by _turboscan and turbosplot
#
def _turbo_ppoint '{
local i ts_idx ts_str _X
ts_str = sprintf("%d",TS_NBCHA+1)
for (i=0; i<PLOT_NO; i++) {
if ((ts_idx=TS_IDX[PLOT_LIST[i]]) != -1)
ts_str = sprintf("%s,%d",ts_str,ts_idx+1)
}
data_plot(TS_ARRAY[:TS_NPTS-1][ts_str])
_X = TS_NBCHA+1
plot_move(-50,0,ts_res1)
plot_move(-50,1,ts_res2)
}'
def ts_res1 'sprintf("Peak at %.5g%s is %.5g. COM at %.5g%s. ",\ TS_xMAX,UL,TS_MAX,TS_COM,UL)'
def ts_res2 'sprintf("FWHM is %.5g%s at %.5g%s. ",\
TS_FWHM,UL,TS_CFWHM,UL)'
def TS_FWHM 'array_op("fwhm", TS_ARRAY[:TS_NPTS-1][_X], TS_ARRAY[:TS_NPTS-1][ts_idx+1])'
def TS_CFWHM 'array_op("cfwhm", TS_ARRAY[:TS_NPTS-1][_X], TS_ARRAY[:TS_NPTS-1][ts_idx+1])'
def TS_xMAX 'array_op("x_at_max", TS_ARRAY[:TS_NPTS-1][_X], TS_ARRAY[:TS_NPTS-1][ts_idx+1])'
def TS_MAX 'array_op("max", TS_ARRAY[:TS_NPTS-1][ts_idx+1])'
def TS_COM 'array_op("com", TS_ARRAY[:TS_NPTS-1][_X], TS_ARRAY[:TS_NPTS-1][ts_idx+1])'
def ts_define_empty_stubs '
if (!(whatis("ts_user_measure")&2)) rdef ts_user_measure ""
'
ts_define_empty_stubs
#%MACROS%
#%IMACROS%
#%AUTHOR%
# TURBOSCAN.MAC J.K - R.P 9-96
#%TOC%
|