#%TITLE% oscilPX.mac
#%NAME%
# Macros handling the oscillation for MX beamlines
#%CATEGORY% MX
#%END%
global OSCIL_CALCACC OSCIL_CALCVELOCITY OSCIL_CALCSLOPE
global OSCIL_DEFACC OSCIL_DEFVELOCITY # default values from config
global OSCIL_MOTOR_NUM OSCIL_MOTOR_NAME
global OSCIL_PREDELAY OSCIL_POSTDELAY
global OSCIL_STEP_MARGIN
global OSCIL_PREDELAY_STEPS OSCIL_POSTDELAY_STEPS
global OSCIL_START_ANGLE OSCIL_FINAL_ANGLE
global MUSST_MARGIN MUSST_INTEGRATION_FACTOR MUSST_SAMPLING MUSST_INTEGRATED_COUNTS
global DIAGFILE
global DIAG_N
global OLDPREF MCCD_OLDDIR
MUSST_MARGIN = 10
MUSST_INTEGRATION_FACTOR = 1
MUSST_SAMPLING = 300
MUSST_INTEGRATED_COUNTS = 0
# array to contain diagnostic information from MUSST
float array musstdiag[100000][7]
#%UU%
#%MDESC%
#
# Oscillation setup macro
#
# It has to be called once to setup values for axis control
# and synchronization
#
def oscilsetup '{
local lerr_msg
spec_par("modify_step_size",1)
if ($#) {
OSCIL_MOTOR_NAME = "$1"
OSCIL_PREDELAY = $2
OSCIL_POSTDELAY = $3
OSCIL_STEP_MARGIN = $4
} else {
OSCIL_MOTOR_NAME = sprintf("%s",getval("Axis mnemonics", OSCIL_MOTOR_NAME))
OSCIL_PREDELAY = getval ("Shutter pre-delay [ms]", OSCIL_PREDELAY)
OSCIL_POSTDELAY = getval ("Shutter posr-delay [ms]", OSCIL_POSTDELAY)
OSCIL_STEP_MARGIN = getval ("Delay before shutter open/after shutter close positions [steps])", OSCIL_STEP_MARGIN)
}
OSCIL_MOTOR_NUM = motor_num(OSCIL_MOTOR_NAME)
if (OSCIL_MOTOR_NUM < 0) {
lerr_msg = sprintf("Error: Motor %s doesn\'t exist", OSCIL_MOTOR_NAME)
fatal( lerr_msg )
}
#
# Store the default velocity and acceleration of the axis
#
cdef("cleanup_always","phi_cleanup;","scan",0x10)
}'
def oscil_on '{
cdef("osc_scan", "oscillation \$*", "_pxoscil",0x20)
cdef("osc_prepare", "oscillation_prepare \$*","_pxoscil",0x20)
}'
def oscil_off '{
cdef("","","_pxoscil","delete")
}'
def oscillation_prepare '{
_oscillation_prepare( $1, $2, $3, $4 )
}'
def _oscillation_prepare(start_ang, stop_ang, exp_time, nb_pass) '{
local abs_ang osctime
cdef("cleanup_once","oscil_cleanup;","scan",0x10)
abs_ang = fabs(stop_ang - start_ang)
osctime = exp_time / nb_pass
velocity = abs_ang / osctime
step_size = fabs(motor_par( OSCIL_MOTOR_NUM, "step_size" ))
OSCIL_CALCVELOCITY = velocity * step_size
OSCIL_CALCACC = osc_acceleration( osctime )
step_time = (1/(OSCIL_CALCVELOCITY)) * 1000
OSCIL_PREDELAY_STEPS = fabs(int(OSCIL_PREDELAY / step_time))
OSCIL_POSTDELAY_STEPS = fabs(int(OSCIL_POSTDELAY / step_time))
OSCIL_CALCSLOPE = osc_slope(velocity, OSCIL_CALCACC, step_size)
printf("converted to : predelay = %d steps, postdelay = %d steps.\n", OSCIL_PREDELAY_STEPS, OSCIL_POSTDELAY_STEPS)
if ( start_ang < stop_ang ) {
OSCIL_START_ANGLE = start_ang - 1.5 * OSCIL_CALCSLOPE
OSCIL_FINAL_ANGLE = stop_ang + 1.5 * OSCIL_CALCSLOPE
} else {
OSCIL_START_ANGLE = start_ang + 1.5 * OSCIL_CALCSLOPE
OSCIL_FINAL_ANGLE = stop_ang - 1.5 * OSCIL_CALCSLOPE
}
#set the integration factor as function of the current gain
MUSST_INTEGRATION_FACTOR = W_GAINF["i1"][sprintf ("%d",wcreadgain("i1")-1)]
# move as fast as possible to the init angle
motor_par( OSCIL_MOTOR_NUM, "velocity", motor_par(OSCIL_MOTOR_NUM, "config_velocity"))
osc_goto( OSCIL_START_ANGLE )
# set velocity and acceleration for the oscillation
motor_par(OSCIL_MOTOR_NUM, "velocity", OSCIL_CALCVELOCITY)
motor_par(OSCIL_MOTOR_NUM, "acceleration", OSCIL_CALCACC)
}'
def test_oscillation '{
printf("Oscillation prepare, start angle=%f, stop angle=%f, exposure time=%f, nb_passes=%d\n", $1, $2, $3, $4)
bench oscillation_prepare $1 $2 $3 $4
print "Oscillation"
bench oscillation $1 $2 $3 $4
}'
def oscillation '{
_oscillation( $1, $2, $3, $4 )
}'
def _oscillation(start_trigger_ang, stop_trigger_ang, exp_time, nb_pass) '{
local i
cdef("cleanup_once", "musst_shutter_reset; phi_cleanup;", "oscillation")
step_size = motor_par(OSCIL_MOTOR_NUM, "step_size")
start_trigger_steps = start_trigger_ang * step_size
stop_trigger_steps = stop_trigger_ang * step_size
start_steps = OSCIL_START_ANGLE * step_size
end_steps = OSCIL_FINAL_ANGLE * step_size
waitmove; getangles
musst_prepare(start_trigger_steps, stop_trigger_steps, start_steps, end_steps, OSCIL_PREDELAY_STEPS, OSCIL_POSTDELAY_STEPS)
for ( i=1; i <= nb_pass; i++) {
printf( "\n ** pass number: %d **\n", i)
even = i%2
if ( even ) {
musst_prepare(start_trigger_steps, stop_trigger_steps, start_steps, end_steps, OSCIL_PREDELAY_STEPS, OSCIL_POSTDELAY_STEPS)
osc_goto(OSCIL_FINAL_ANGLE)
} else {
musst_prepare(stop_trigger_steps, start_trigger_steps, end_steps, start_steps, OSCIL_PREDELAY_STEPS, OSCIL_POSTDELAY_STEPS)
osc_goto(OSCIL_START_ANGLE)
}
waitmove; getangles
musst_handle_data i
}
musst_shutter_reset
phi_cleanup
}'
def osc_goto( target_angle ) '{
waitmove; get_angles
if ( fabs( A[OSCIL_MOTOR_NUM] - target_angle ) < 0.001 ) {
return
}
if (motor_par(OSCIL_MOTOR_NUM,"disable")==0) {
UPDATE_DELAY=1
A[OSCIL_MOTOR_NUM] = target_angle
move_em
UPDATE_DELAY=0
} else {
fatal(sprintf("Cannot move DISABLED motor %s, exiting\n",motor_mne(OSCIL_MOTOR_NUM)))
}
}'
def osc_acceleration( osctime ) '{
return 100
}'
def osc_slope( velocity, acceleration, step_size ) '{
slope = fabs( (velocity * (acceleration / 1000)) + (OSCIL_STEP_MARGIN/step_size) ) / 2.0
return slope
}'
#
# Cleanup Macros
#
# Cleanup during oscillation
def oscil_cleanup '{
msclose
phi_cleanup
musst_cleanup
}'
#%IU%
#%MDESC%
# Restore phi parameters
def phi_cleanup '{
local defvel defacc
print "doing phi cleanup"
defvel = motor_par(OSCIL_MOTOR_NUM,"config_velocity")
defacc = motor_par(OSCIL_MOTOR_NUM,"config_acceleration")
motor_par( OSCIL_MOTOR_NUM, "velocity", defvel)
motor_par( OSCIL_MOTOR_NUM, "acceleration", defacc)
}'
def musst_prepare(start_steps, stop_steps, init_steps, final_steps, predelay, postdelay) '{
local step_size phi_steps
local msg musst_hexa
printf(" - predelay = %d steps, postdelay = %d steps\n", predelay, postdelay)
# load current encoder value in MUSST
step_size = motor_par( OSCIL_MOTOR_NUM, "step_size")
phi_steps = A[OSCIL_MOTOR_NUM] * step_size
musstPX_init(phi_steps)
if ( start_steps < stop_steps ) {
start_steps -= predelay
stop_steps -= postdelay
init_steps += MUSST_MARGIN
} else {
start_steps += predelay
stop_steps += postdelay
init_steps -= MUSST_MARGIN
}
musstPX_oscill(init_steps, final_steps, start_steps, stop_steps, MUSST_SAMPLING)
}'
def musst_shutter_reset '{
musstPX_shclose()
}'
def musst_handle_data '{
local npts maxvel nopass
nopass = $1
musst_postoscil
array_op("fill",musstdiag,0,0)
npts = musstPX_read(OSCIL_MOTOR_NUM, musstdiag)
if ( npts != -1 ) musst_save(npts,nopass)
}'
def musst_postoscil '{
local step_size phi_steps musst_steps
local msg
step_size = motor_par( OSCIL_MOTOR_NUM, "step_size")
phi_steps = A[OSCIL_MOTOR_NUM] * step_size
musst_steps = musstPX_getphi()
msg = sprintf("- oscillation ends. \n")
msg = sprintf("%s PHI is now at %4.4f ( %d steps )\n", msg, A[phi],phi_steps)
msg = sprintf("%s MUSST shows %d steps\n", msg, musst_steps)
print msg
}'
def musst_save(npts,passno) '{
global MUSST_INTEGRATED_COUNTS CURRENT_IMAGE_INTENSITY
local i imgname curdir curpref npasses bkgrd bkgd_pts bkgd_average averaged_counts_per_pass
local bkgd2 sigma_bkgr nsigma bkgd_pt
local integrated_counts_per_pass cal
curdir = COLLECT_SEQ["fileinfo"]["directory"]
curpref = sprintf("%s_%d", COLLECT_SEQ["fileinfo"]["prefix"], COLLECT_SEQ["fileinfo"]["run_number"])
npasses = COLLECT_SEQ["number_of_passes"]
averaged_counts_per_pass = 0
if ( OLDPREF != curpref || OLDDIR != curdir) {
DIAG_N = 0
DIAGFILE = sprintf("%s/%s_diag.dat", curdir, curpref )
OLDPREF = curpref
OLDDIR = curdir
}
diagname = sprintf("%s pass %d", getMxCollectPars("current_filename"), passno)
printf(" - Saving diagnostics for %s to file: \n\t\t%s\n", diagname, DIAGFILE)
HEADING = diagname
savefileheader(DIAGFILE, 1)
savestdheader(DIAGFILE, 4, DIAG_N)
fprintf(DIAGFILE, "#N %d\n",array_op("cols", musstdiag))
fprintf(DIAGFILE, "#L Time(ms) Speed Phi I1 I0 Shut Cmd IR sensor\n")
on(DIAGFILE);offt
array_dump( musstdiag[0:npts-1] )
ont; off(DIAGFILE); close(DIAGFILE)
bkgd=0; bkgd2=0; sigma_bkgr=0; bkgd_pts=0; signal_pts=0;
for (i=0;i<npts;i++) {
if (musstdiag[i][5] == 0) {
bkgd_pt = (musstdiag[i][3])*COLLECT_SEQ["exposure_time"]/npasses
bkgd = bkgd + bkgd_pt
bkgd2 = bkgd2 + (bkgd_pt*bkgd_pt)
bkgd_pts += 1
} else {
integrated_counts_per_pass += (musstdiag[i][3])*COLLECT_SEQ["exposure_time"]/npasses
signal_pts += 1
}
}
if (signal_pts < 1) signal_pts = 1
if (bkgd_pts > 0) {
bkgd_average = bkgd/bkgd_pts
sigma_bkgd= (bkgd2/bkgd_pts) - (bkgd_average*bkgd_average)
if (sigma_bkgd < 0.001) sigma_bkgd = 0.001
sigma_bkgd= sqrt(sigma_bkgd)
printf("sigma background (%6.3f) is sqrt ((sum of bkgd_squared (%6.2g)/bkgd pts (%6.2f) - (bkgd_average (%6.2g) _squared) )\n", sigma_bkgd,bkgd2,bkgd_pts,bkgd_average)
} else {
bkgd_average = 0
}
bkgd = bkgd_average * signal_pts
integrated_counts_per_pass = integrated_counts_per_pass - bkgd
averaged_counts_per_pass = integrated_counts_per_pass / signal_pts
nsigma = (averaged_counts_per_pass - bkgd_average) / sigma_bkgd
printf("Nsigma (%6.3f) (should be bigger than 2) will be (averaged_counts_per_pass (%6.3f) - bkgd_average (%6.3f)) / sigma_background (%6.2f)\nsignal_avg %f and total points %d\n", nsigma,averaged_counts_per_pass,bkgd_average, sigma_bkgd,integrated_counts_per_pass/signal_pts,npts)
if (fabs(nsigma) < 2) {
printf(" - background and X-rays indistinguishable. Check i1 (ct in spec)\n")
egui_logmsg(sprintf("Measured values for background and X-ray intensity not very distinguishable. \n"))
#MUSST_INTEGRATED_COUNTS += 0.0
MUSST_INTEGRATED_COUNTS += fabs(averaged_counts_per_pass)
} else {
MUSST_INTEGRATED_COUNTS += fabs(averaged_counts_per_pass)
printf(" - integrated counts for pass %d = %g (background = %g)\n", passno, MUSST_INTEGRATED_COUNTS, bkgd)
}
if (passno == npasses) {
cal = flux_get_calibration()
corrected_counts = \
cal[1] * MUSST_INTEGRATED_COUNTS * MUSST_INTEGRATION_FACTOR
printf("Musst integrated counts: %f\n",MUSST_INTEGRATED_COUNTS)
CURRENT_IMAGE_INTENSITY=corrected_counts
HDBCURR_INT=corrected_counts
CURRENT_IMAGE_INTENSITY=corrected_counts
# last pass
printf(" - saving integrated counts to diag. file\n")
egui_logmsg(sprintf("Integrated counts for image : %.6g\n", corrected_counts))
fprintf(DIAGFILE, "\n#S %d\n#N 1\n", DIAG_N+1)
fprintf(DIAGFILE, "#L Integrated counts\n")
fprintf(DIAGFILE, "%g\n", corrected_counts)
MUSST_INTEGRATED_COUNTS=0
corrected_counts=0
}
close(DIAGFILE)
DIAG_N++
}'
def musst_cleanup '{
musst_comm("ABORT")
musstPX_shclose()
}'
def fatal( msg ) '{
tty_cntl("md")
printf ("<OSCIL> -abort- %s\n", msg)
egui_logmsg(sprintf("<OSCIL>abort_from_spec %s", msg))
tty_cntl("me")
exit
}'
#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% BLISS%BR%
#$Revision: 1.24 $$Date: 2012/05/10 14:46:42 $
#%END%
#%LOG%
#$Log: oscilPX.mac,v $
#Revision 1.24 2012/05/10 14:46:42 guijarro
#added phi cleanup
#
#Revision 1.23 2010/11/02 12:47:42 beteva
#set MUSST_INTEGRATION_FACTOR as function of the current Novelec gain.
#apply it for the integrated flux calculation
#
|