#%TITLE% mxcollect.mac
#%NAME% %B%mxcollect.mac%B% - macro set for MX datacollection
#%END%
global datacollection_parameters
global SAFETY_SHUTTER_DEVICE
global CURRENT_IMAGE
global STOP_COLLECT_LOOP
global eprodc_log_message
global eprodc_fatal_collect[]
global eprodc_energy_scan_msg
global OLD_COLLECT_SEQ[]
global _ecollect_retDict[]
global COLLECT_SEQ[]
global CURRENT_FRAME_NUMBER
if (whatis("local_skip_images") == 0)
eval("def local_skip_images() \'{}\'")
### Convert the dictionary from python into COLLECT_SEQ
def build_collect_seq() '{
global datacollection_parameters[]
unglobal COLLECT_SEQ
global COLLECT_SEQ[]
local sequence_pars[]
local sequence
sequence = datacollection_parameters["oscillation_sequence"]
if (EPRODC_DEBUG==1)
print datacollection_parameters
sequence = sprintf("[%s]", substr(sequence, 3, length(sequence)-4))
if (EPRODC_DEBUG==1)
print sequence
COLLECT_SEQ=eval(sequence)
for (el in datacollection_parameters) {
if (el != "oscillation_sequence") {
COLLECT_SEQ[el]=datacollection_parameters[el]
}
}
if (!COLLECT_SEQ["detector_mode"]) {
inp[0] = "detector"; inp[1] = "binning"
COLLECT_SEQ["detector_mode"] = getMxSpecPars(inp)
}
}'
def datacollection() '{
egui_fatal("Could not get control of the minidiff")
SCMinidiffGetControl
if (SCMinidiffCanMove()!=1) {
exit
}
unglobal eprodc_fatal_collect
global eprodc_fatal_collect[]
build_collect_seq()
ecollect()
return _ecollect_retDict
}'
def eprodc_set_mono() '{
local requested_egy
if (whatis("COLLECT_SEQ[\"energy\"]")>>16&0x8000) {
requested_egy = COLLECT_SEQ["energy"]
} else {
if (whatis("COLLECT_SEQ[\"wavelength\"]")>>16&0x8000) {
requested_egy = hc_over_e/COLLECT_SEQ["wavelength"]
}
}
if (requested_egy == 0) {
# no energy is specified, just ignore
if (EPRODC_DEBUG==1) print "No energy specified from mxCuBE, ignoring"
return 1
}
if (fabs(getMxEnergy() - requested_egy)<0.002) {
if (EPRODC_DEBUG == 1) print "Energy is already set properly"
return 1
}
if (EPRODC_DEBUG == 1) print "Requested energy is " requested_egy
check_beam()
prodc_set_mono requested_egy
return 1
}'
def eprodc_transmission() '{
if (whatis("COLLECT_SEQ[\"transmission\"]")>>16&0x8000) {
if (EPRODC_DEBUG == 1) print "Setting TRANSMISSION to " COLLECT_SEQ["transmission"]
transmission COLLECT_SEQ["transmission"]
# need to add a check here to see if we did it
}
return 1
}'
def eprodc_moveDetector() '{
local detmot,distance
distance=-1
if (whatis("COLLECT_SEQ[\"resolution\"][\"upper\"]")>>16&0x8000) {
if (EPRODC_DEBUG == 1) print "Move detector to resolution " COLLECT_SEQ["resolution"]["upper"]
get_angles
distance = CalculateDistanceFromResolution(COLLECT_SEQ["resolution"]["upper"])
} else if (whatis("COLLECT_SEQ[\"detdistance\"]")>>16&0x8000) {
if (EPRODC_DEBUG == 1) print "Move detector to " COLLECT_SEQ["detdistance"]
distance=COLLECT_SEQ["detdistance"]
}
if (distance!=-1) {
detmot = motor_num(getMxSpecPars("detdistmot"))
_bad_lim =0
backlash = motor_par(detmot,"backlash")/motor_par(detmot,"step_size")
_chk_lim detmot distance-backlash
if (_bad_lim>0) {
datacollection_cleanup
return -1
}
A[detmot] = distance
move_em
waitmove
return distance
} else {
# we do not have an input resolution so no problem
return 1
}
}'
# takes one argument, collectmode- which determines if to skip
# already existing images or not
#
def ecollect() '{
global STOP_COLLECT_LOOP COLLECT_SEQ
global CURRENT_IMAGE_FILENAME CURRENT_IMAGE_NUMBER CURRENT_IMAGE_INTENSITY
global MXSPEC_PARS
unglobal CURRENT_IMAGE
global CURRENT_IMAGE
unglobal _ecollect_retDict
global _ecollect_retDict[]
local osc_start osc_range osc_overlap npass \
exptime nframes comment
cdef("cleanup_once","datacollection_cleanup;","_collect")
# The STOP_COLLECT_LOOP variable will be set externally from the GUI via specserver
STOP_COLLECT_LOOP=0
if (eprodc_transmission() == -1) {
egui_fatal("Could not achieve the required transmission")
exit
}
egui_logmsg("Set transmission")
if (eprodc_set_mono() == -1 ) {
egui_fatal("Could not achieve the required energy")
exit
}
egui_logmsg("Set monochromator to right energy")
if (eprodc_moveDetector() == -1) {
egui_fatal("Could not achieve required resolution")
exit
}
egui_logmsg("Set detector to right distance")
#
# perhaps this should be moved down to after the first ccdprep
# this would keep the shutter closed while darks are taken
#
prodc_prepare_beamline
egui_logmsg("Beamline prepared")
get_angles
_ecollect_retDict["curr_detdistance"] = getMxCurrentDistance()
_ecollect_retDict["curr_wavelength"] = getMxWavelength()
_ecollect_retDict["curr_resolution"] = CalculateResolutionFromDistance()
_ecollect_retDict["curr_transmission"] = getMxCurrentTransmission()
_ecollect_retDict["xbeam"] = getMxBeamCentreX()
_ecollect_retDict["ybeam"] = getMxBeamCentreY()
_ecollect_retDict["undulatorGap0"] = getMxUndulatorGap(1)
_ecollect_retDict["undulatorGap1"] = getMxUndulatorGap(2)
_ecollect_retDict["undulatorGap2"] = getMxUndulatorGap(3)
_ecollect_retDict["undulatorType0"] = getMxUndulatorType(1)
_ecollect_retDict["undulatorType1"] = getMxUndulatorType(2)
_ecollect_retDict["undulatorType2"] = getMxUndulatorType(3)
_ecollect_retDict["slitGapHorizontal"] = getMxSlitGapHorizontal()
_ecollect_retDict["slitGapVertical"] = getMxSlitGapVertical()
_ecollect_retDict["beamShape"] = getMxBeamShape()
_ecollect_retDict["beamSizeAtSampleX"] = getMxBeamSizeX()
_ecollect_retDict["beamSizeAtSampleY"] = getMxBeamSizeY()
_ecollect_retDict["resolutionAtCorner"] = getMxResolutionAtCorner()
_ecollect_retDict["resolutionAtHalfCorner"] = getMxResolutionAtHalfCorner()
local_skip_images()
osc_start = COLLECT_SEQ["start"]
osc_range = COLLECT_SEQ["range"]
osc_overlap = COLLECT_SEQ["overlap"]
npass = COLLECT_SEQ["number_of_passes"]
exptime = COLLECT_SEQ["exposure_time"]
nframes = COLLECT_SEQ["number_of_images"]
comment = COLLECT_SEQ["comment"]
getMxTotalParams()
# for mxCuBE to trigger a dark current
MXCOLLECT_PARS["TakeDarkFlag"] = COLLECT_SEQ["dark"]
# Make sure the fast shutter is closed, important for some h/w configurations
msclose
getangles
local tmp[]
split(comment, tmp, ",")
for (k in tmp) {
local motmne, pos
local i, j, s
s = tmp[k]
i = index(s, ":")
if (i > 0) {
motmne = substr(s, 1, i-1)
motnum = eval(sprintf("motor_num(%s)", motmne))
if (motnum < 0) {
print "invalid motor " motmne
} else {
pos = substr(s, i+2)
pos = pos + 0
printf("Preparing to move motor %s to %f\n", motmne, pos)
A[motnum] = pos
}
}
}
print "Waiting for motors to move"
move_em; waitmove
write_dp_inputs(COLLECT_SEQ,MXBCM_PARS)
# D.S 20100304
# This is a corruption of this macro which should not have equipment specific commands embedded in it
#
if (motor_par(phi, "device_id")!="udiff_mot") { musstPX_loadprog }
# set up the detector in the desired mode (set by the GUI)
# and program the header parameters
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
ccdprep(MXCOLLECT_PARS["TakeDarkFlag"],osc_start,osc_range,exptime,npass,comment)
egui_logmsg("Detector prepared")
}
shopen
egui_logmsg("Safety shutter open")
# adjust the gain for the integrated counts
adjust_i0_i1_gain()
# initialisation for the first frame
local angles[] wedgesize first_run_number inverse_run_number frame
initial_start_angle = osc_start
initial_stop_angle = initial_start_angle + osc_range
angles[0] = initial_start_angle
angles[1] = initial_stop_angle
if (fabs(angles[0] - angles[1]) > 0.0001) {
osc_prepare initial_start_angle initial_stop_angle exptime npass
} else {
print "moving phi to " initial_start_angle "for still image"
osc_goto(initial_start_angle); waitmove
}
egui_logmsg("First oscillation prepared")
if (index(COLLECT_SEQ["experiment_type"],"Inverse") > 0) {
first_run_number = COLLECT_SEQ["fileinfo"]["run_number"]
inverse_run_number = COLLECT_SEQ["fileinfo"]["run_number"]+1
wedgesize = COLLECT_SEQ["reference_interval"]
for (frame=0;frame< nframes;frame++) {
egui_logmsg("Starting inverse beam")
for (wedge=1; wedge <= wedgesize; wedge++) {
egui_logmsg(sprintf("Wedge %d of %d",wedge,wedgesize))
notskipped = collect_frame(angles[0],angles[1],\
exptime,npass,\
first_run_number,\
frame + wedge -1,\
nframes)
if (wedgesize != wedge ) {
angles = prepare_next_start_angle(initial_start_angle,initial_stop_angle,\
exptime,npass,osc_overlap,\
wedge + frame -1, \
nframes)
}
if (STOP_COLLECT_LOOP == 1) { frame=nframes-1; wedge=wedgesize }
if (notskipped == 1) {
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
if (frame == nframes -1) { ccdflush } else { ccdsave}
}
wedge = mxcol_checkIntensity(wedge-1)+1
}
}
angles = prepare_next_start_angle(initial_start_angle+180,initial_stop_angle+180,\
exptime,npass,osc_overlap,\
(frame-1),\
nframes)
for (wedge=1; wedge <= wedgesize; wedge++) {
notskipped = collect_frame(angles[0],angles[1],\
exptime,npass,\
inverse_run_number,\
frame+ wedge -1,\
nframes,1)
if (wedgesize != wedge ) {
angles = prepare_next_start_angle(initial_start_angle+180,initial_stop_angle+180,\
exptime,npass,osc_overlap,\
wedge + frame -1,\
nframes)
}
if (STOP_COLLECT_LOOP == 1) { frame=nframes-1; wedge=wedgesize }
if (notskipped == 1) {
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
if (frame == nframes -1) {ccdflush } else { ccdsave}
}
wedge = mxcol_checkIntensity(wedge-1)+1
}
}
frame+=wedgesize-1
if ((nframes - frame) <= wedgesize ) wedgesize = nframes - frame - 1
angles = prepare_next_start_angle(initial_start_angle,initial_stop_angle, \
exptime,npass,osc_overlap,\
frame,\
nframes)
}
} else {
for (frame=0;frame< nframes;frame++) {
notskipped = collect_frame(angles[0],angles[1],\
exptime,npass,\
COLLECT_SEQ["fileinfo"]["run_number"],\
frame,\
nframes)
if (STOP_COLLECT_LOOP == 1) frame=nframes-1
if (notskipped == 1) {
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
if (frame == nframes -1) {ccdflush } else { ccdsave}
}
frame = mxcol_checkIntensity(frame)
}
angles = prepare_next_start_angle(initial_start_angle,initial_stop_angle,\
exptime,npass,osc_overlap,\
frame,\
nframes)
}
}
COLLECT_SEQ["successful"]=1
datacollection_cleanup
_ecollect_retDict["code"]=2005
_ecollect_retDict["message"]="Data collection completed"
#print _ecollect_retDict
return _ecollect_retDict
}'
def prepare_next_start_angle(initial_start_angle,initial_stop_angle,exptime,npass,overlap,frame,nframes) '{
local return_angles[] range
# prepare next oscillation
if ((nframes > 1) && (frame < nframes - 1)) {
range = initial_stop_angle - initial_start_angle
n_start_angle = initial_start_angle+(frame + 1)*range - (frame + 1)*overlap
n_stop_angle = n_start_angle + range
if (STOP_COLLECT_LOOP == 0)
if (fabs(range) > 0.0001) {
osc_prepare n_start_angle n_stop_angle exptime npass
} else {
print "moving phi to " n_start_angle "for still image"
osc_goto(n_start_angle); waitmove
}
return_angles["next_initial_start_angle"]=n_start_angle
return_angles["next_initial_stop_angle"]=n_stop_angle
} else {
return_angles["next_initial_start_angle"]=-1
return_angles["next_initial_stop_angle"]=-1
}
return [0:return_angles["next_initial_start_angle"],1:return_angles["next_initial_stop_angle"]]
}'
# dummy macro needed for if the hook is not defined in collect_frame
def specific_collect_frame_hook(a,b,c,d,e,f,g,h,i,j,k,l) '{
}'
def collect_frame(start_angle,stop_angle,exptime,npass,run_number, frame,nframes,inv) '{
global CURRENT_FRAME_NUMBER
local collectedFrameFlag current_image_trigger
setMxCollectPars("current_phi",start_angle)
# modify the run number according to what was asked for
COLLECT_SEQ["fileinfo"]["run_number"]=run_number
imagefile = ccdfile(COLLECT_SEQ,frame)
setMxCurrentFilename(imagefile)
_ecollect_retDict["run_number_total"] += run_number
CURRENT_FRAME_NUMBER = frame + COLLECT_SEQ["start_image_number"]
if ((COLLECT_SEQ["skip_images"]==0) || (file_info(imagefile)==0)) {
egui_logmsg(sprintf("Frame %d, %7.3f to %7.3f degrees",frame+COLLECT_SEQ["start_image_number"],start_angle,stop_angle))
# prepare next start angle here if skip was selected using the previous frame counter to give the right angle for this image
if ((COLLECT_SEQ["skip_images"]== 1)&&(file_info(imagefile)!=0))
prepare_next_start_angle(COLLECT_SEQ["start"],COLLECT_SEQ["start"]+COLLECT_SEQ["range"],exptime,npass,overlap,frame-1,nframes)
# the following waitmove ensures that the detector is not exposing too long
# while the phi is still moving to the start angle
waitmove
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
ccdstart
}
if (fabs(start_angle - stop_angle) < 0.0001) {
msopen; sleep(exptime); msclose
} else {
osc_scan start_angle stop_angle exptime npass frame
}
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
ccdread
}
_ecollect_retDict["total_start_angles"]+= start_angle
_ecollect_retDict["total_stop_angles"]+= stop_angle
_ecollect_retDict["total_passes"]+= npass
_ecollect_retDict["total_exposure"]+= exptime
_ecollect_retDict["im_collected"]++
_ecollect_retDict["intensity"] = CURRENT_IMAGE_INTENSITY
_ecollect_retDict["totalintensity"] += CURRENT_IMAGE_INTENSITY
_ecollect_retDict["previous_intensity"] = CURRENT_IMAGE["measuredIntensity"]
collectedFrameFlag=1
# save image in database
#current_image_trigger["image_number"] = frame+COLLECT_SEQ["start_image_number"]
#current_image_trigger["image_file"] = imagefile
#current_image_trigger["measuredIntensity"] = CURRENT_IMAGE_INTENSITY
# setting CURRENT_IMAGE will trigger mxCuBE to store the information
# in the database.
# CURRENT_IMAGE=current_image_trigger
delete CURRENT_IMAGE["image_number"]
CURRENT_IMAGE["image_file"] = imagefile
CURRENT_IMAGE["measuredIntensity"] = CURRENT_IMAGE_INTENSITY
CURRENT_IMAGE["image_number"] = frame+COLLECT_SEQ["start_image_number"]
} else {
msg=(sprintf("%s already exists, so skipping...",imagefile))
egui_logmsg(msg) ; print msg
if ( COLLECT_SEQ["detector_mode"] != 3 ) {
if (frame == nframes -1) ccdflush
}
collectedFrameFlag=0
}
if ((whatis("specific_collect_frame_hook")&2)>>1) {
specific_collect_frame_hook(start_angle,stop_angle,exptime,npass,run_number, frame,nframes,inv,imagefile,CURRENT_IMAGE_INTENSITY)
}
return(collectedFrameFlag)
}'
def mxcol_checkIntensity(frame) '{
local checkIntensityRetval
print "mxcol_checkIntensity frame " frame
# do something if the intensity has dropped by more than 90 percent
checkIntensityRetval = 0
if (I0THRESHOLD != 0) {
if (_ecollect_retDict["previous_intensity"] > 0.0 || frame ==0) {
# if there were no counts on the 1st image force a wait
if (frame ==0 && CURRENT_IMAGE_INTENSITY < I0THRESHOLD) {
_ecollect_retDict["previous_intensity"]= CURRENT_IMAGE_INTENSITY*10 + 1
} else if (_ecollect_retDict["previous_intensity"] < 0.1) {
# we need an initial value for the previous intensity!
_ecollect_retDict["previous_intensity"]=1.0
}
if (CURRENT_IMAGE_INTENSITY/_ecollect_retDict["previous_intensity"] < 0.1) {
print "Checking the intensity...."
mxWaitForBeam()
checkIntensityRetval = 1
}
}
# rewind 2 frames if possible
if (checkIntensityRetval ==1) {
print "We decided to wait for Beam!"
if (frame > 1) {
frame = frame -2
} else if (frame == 0) {
frame = frame -1
}
}
} else {
print "Wait for beam disabled while I0THRESHOLD=0. To enable this set I0THRESHOLD to the minimum I0 counts required"
}
return(frame)
}'
def mxWaitForBeam() '{
local exitCondition I0Intensity
exitCondition=0
I0Intensity=0
while (I0Intensity < I0THRESHOLD && exitCondition==0) {
sleep(1)
ct 0.1
I0Intensity = S[i0]
printf("Counts are %6.4e, waiting for > %6.4e\n",I0Intensity,I0THRESHOLD)
if (I0Intensity > I0THRESHOLD) exitCondition=1
}
}'
def datacollection_cleanup '{
egui_logmsg("doing data collection cleanup...")
printf("collect cleanup initiated\n")
# The STOP_COLLECT_LOOP variable will be set externally from the GUI via specserver
unglobal datacollection_parameters
global datacollection_parameters
msclose
if ((COLLECT_SEQ["in_queue"]==0)||(STOP_COLLECT_LOOP==1)) {
shclose
} else if ((COLLECT_SEQ["in_queue"]==1) && (COLLECT_SEQ["successful"]==0)) {
# we should not close the shutter, but something wrong happened with
# last image... so we close it anyway
shclose
}
prodc_finish_beamline
phi_cleanup
# remove the data collection parameters
OLD_COLLECT_SEQ=COLLECT_SEQ
unglobal COLLECT_SEQ
global COLLECT_SEQ[]
STOP_COLLECT_LOOP=0
}'
def validate_collect_parameters() '{
global datacollection_parameters
local result validpars par
# code values -1=error 0 = warning, 1=ok
inp[0]=""
result["code"] = 1
result["msg"] = ""
# build the spec array from the python format input given by mxCuBE
build_collect_seq()
for (par in MXVALIDATE_PARS) {
split(MXVALIDATE_PARS[par],inp,",")
minval = inp[0] + 0.0
maxval = inp[1] + 0.0
if (COLLECT_SEQ[par] < minval || COLLECT_SEQ[par] > maxval) {
result["code"] = 0
result["msg"] = sprintf("%s\nThe value for %s (%6.2f) is outside the normal values (%6.2f to %6.2f)",result["msg"],par,COLLECT_SEQ[par],minval,maxval)
}
}
split(MXEXTRAVALIDATE_PARS["rotation_speed"],inp,",")
min = inp[0] + 0.0;max = inp[1]+0.0
if (COLLECT_SEQ["exposure_time"] > 0.001) {
phi_speed = COLLECT_SEQ["range"]/ \
(COLLECT_SEQ["exposure_time"]/COLLECT_SEQ["number_of_passes"])
} else {
phi_speed = 1.0E99
}
if (HELICAL_OSCIL == 1) {
result["code"]=0
result["msg"]="Helical oscillation is ON"
#if (COLLECT_SEQ["overlap"] != 0) {
# result["code"]=-1
# result["msg"]= sprintf("%s\nSorry, cannot use overlap with helical oscillation on", result["msg"])
#}
if (helical_check() == -1) {
result["code"]=-1
result["msg"]= sprintf("%s\n%s", result["msg"],HELICAL_PARS["msg"])
}
}
if (COLLECT_SEQ["number_of_images"]>4 && COLLECT_SEQ["overlap"] < -1) {
result["code"] = 0
result["msg"] = sprintf("%s\nAre you sure you want to collect %d images with an overlap of %6.1f?",result["msg"],COLLECT_SEQ["number_of_images"],COLLECT_SEQ["overlap"])
}
if (COLLECT_SEQ["overlap"] == 1) {
result["code"] = 0
result["msg"] = sprintf("%s\nAre you sure you want to collect %d images with an overlap of %6.1f?",result["msg"],COLLECT_SEQ["number_of_images"],COLLECT_SEQ["overlap"])
}
inp[0] = "detector"; inp[1] = "binning"
default_bin_mode = getMxSpecPars(inp)
if (whatis("COLLECT_SEQ[\"detector_mode\"]")>>16&0x8000) {
if (default_bin_mode != COLLECT_SEQ["detector_mode"]) {
result["code"] = 0
result["msg"] = sprintf("%s\nThe detector binning mode (%d) (0=software binned, 1=unbinned, 2=hardware binned) is not the default (%d).",result["msg"],COLLECT_SEQ["detector_mode"],default_bin_mode)
}
}
if (phi_speed > max) {
result["code"] = -1
result["msg"] = sprintf("%s\nThe calculated axis rotation speed (%6.2f degrees/sec) is faster than the acceptable limit for the hardware (%6.2f to %6.2f)",result["msg"],phi_speed,min,max)
}
if (phi_speed < min ) {
result["code"] = 0
result["msg"] = sprintf("%s\nThe calculated axis rotation speed (%6.2f degrees/sec) is either 0 or too slow. Please proceed if you have requested still images",result["msg"],phi_speed)
}
return result
}'
def update_collect_parameters() '{
local _parDict
_parDict["curr_detdistance"] = getMxCurrentDistance()
_parDict["curr_wavelength"] = getMxWavelength()
_parDict["curr_resolution"] = CalculateResolutionFromDistance()
_parDict["curr_transmission"] = getMxCurrentTransmission()
# now obsolete because mxCuBE should only display the default binning mode
#_parDict["curr_detector_mode"] = getMxDetectorBinMode()
_parDict["FileSuffix"] = getMxDetectorFileSuffix()
_parDict["xbeam"] = getMxBeamCentreX()
_parDict["ybeam"] = getMxBeamCentreY()
inp[0]="detector";inp[1]="type"
_parDict["detector"] = getMxBcmPars(inp)
inp[1]="binning"
_parDict["detector_mode"] = getMxSpecPars(inp)
_parDict["default_number_of_passes"] = getMxBcmPars("default_number_of_passes")
_parDict["minimum_exposure_time"] = getMxBcmPars("minimum_exposure_time")
_parDict["default_exposure_time"] = getMxBcmPars("default_exposure_time")
_parDict["minimum_phi_oscillation"] = getMxBcmPars("minimum_phi_oscillation")
_parDict["maximum_phi_speed"] = getMxBcmPars("maximum_phi_speed")
_parDict["minimum_phi_speed"] = getMxBcmPars("minimum_phi_speed")
_parDict["maximum_exposure"] = getMxBcmPars("maximum_exposure")
# also need beamsize vertical,horizontal, fill mode, min/max exposure time/rotation speed, detector type
return _parDict
}'
# make the gain adjustment to the diode amplifiers to have the right
# dynamic range for the integrated counts.
# The safety shutter is open, so the adjustment is made on i0. The resulting
# gainfactor is applied also to i1 which should be around the same sensitivity.
def adjust_i0_i1_gain() '{
ct 0.1
wcgain i1 wcreadgain(i0)
}'
# prepares the centring: set in light and move zoom to 0
def eprodc_prepare_centring '{
SCMinidiffGetControl
lightin
mv zoom 0
}'
def egui_logmsg(msgtext) '{
global eprodc_log_message
if (EPRODC_DEBUG==1)
printf("egui_logmsg %s\n",msgtext)
eprodc_log_message=msgtext
}'
def egui_fatal(msgtext) '{
unglobal eprodc_fatal_collect
global eprodc_fatal_collect[]
if (EPRODC_DEBUG==1)
printf("egui_fatal %s\n", msgtext)
eprodc_fatal_collect["message"]=msgtext
eprodc_fatal_collect["code"]=-1
eprodc_log_message=msgtext
}'
# below is simulation code for working without beam
global SIMUL_IMAGEFILE SIMUL_IMAGE_CTR
def simul_ccdstart '{
global _ccd_retDict
if (EPRODC_DEBUG==1)
print "simul_ccdstart $1 $2 $3 $4 $5"
egui_logmsg("Simulated detector is integrating")
sleep(0.1)
_ccd_retDict["code"]=0
}'
def simul_ccdread '{
global _ccd_retDict
egui_logmsg("Simulated detector is reading out")
sleep(0.1)
_ccd_retDict["code"]=0
}'
def simul_ccdsave '{
global _ccd_retDict
global SIMUL_IMAGEFILE
SIMUL_IMAGE_CTR = SIMUL_IMAGE_CTR%2
egui_logmsg("Simulated detector is writing image")
cmd = sprintf("cp %s/test%d.img %s.img",COLLECT_SEQ["fileinfo"]["directory"],SIMUL_IMAGE_CTR,SIMUL_IMAGEFILE)
unix(cmd)
sleep(0.1)
SIMUL_IMAGE_CTR++
}'
def simul_ccdflush '{
global _ccd_retDict
SIMUL_IMAGE_CTR = SIMUL_IMAGE_CTR%2
egui_logmsg("Simulated detector is writing image (last image)")
cmd = sprintf("cp %s/test%d.img %s.img",COLLECT_SEQ["fileinfo"]["directory"],SIMUL_IMAGE_CTR,SIMUL_IMAGEFILE)
unix(cmd)
sleep(0.1)
SIMUL_IMAGE_CTR++
}'
def simul_ccdcleanup '{
if (EPRODC_DEBUG==1)
print "ccd_cleanup: well nothing to do for a simulated detector"
}'
def ccd_simulate_on '{
cdef("ccdstart","simul_ccdstart","_pxccd",0x20)
cdef("ccdread","simul_ccdread","_pxccd",0x20)
cdef("ccdcleanup","simul_ccdcleanup","_pxccd",0x20)
cdef("ccdsave","simul_ccdsave","_pxccd",0x20)
cdef("ccdflush","simul_ccdflush","_pxccd",0x20)
cdef("ccdfile","simul_filename","_pxccd",0x20)
cdef("ccdprep","simul_prep","_pxccd",0x20)
}'
def simul_prep(dark,osc_start,osc_range,exptime,npass,comment) '{
if (EPRODC_DEBUG==1)
print "simul_prep"
}'
def simul_filename(cpars,frame) '{
global SIMUL_IMAGEFILE SIMUL_IMAGENUMBER
SIMUL_IMAGENUMBER = cpars["start_image_number"] + frame
SIMUL_IMAGEFILE = sprintf("%s/%s_%d_%03d",cpars["fileinfo"]["directory"],\
cpars["fileinfo"]["prefix"],\
cpars["fileinfo"]["run_number"],\
SIMUL_IMAGENUMBER)
if (EPRODC_DEBUG==1)print "*filename*** " SIMUL_IMAGEFILE
return(SIMUL_IMAGEFILE)
}'
def ccd_simulate_off '{
cdef("","","_pxccd","delete")
}'
def eprodc_energy_scan_status(msg) '{
global eprodc_energy_scan_msg
eprodc_energy_scan_msg=msg
}'
def eprodc_check_safety_shutter() '{
return shstate()
}'
def prodc_prepare_beamline '{
global COLLECT_SEQ
specific_prepare_beamline
# move to centred position (if it exists inside COLLECT_SEQ)
getangles
for (motname in COLLECT_SEQ["centred_pos"]) {
motnum = motor_num(motname)
if (motnum>0) {
motpos=COLLECT_SEQ["centred_pos"][motname]
printf(" - moving %s to %f\n", motname, motpos)
A[motnum]=motpos
} else {
printf(" - unknown motor %s, breaking\n", motname)
getangles
break
}
}
move_em; waitmove
}'
def prodc_finish_beamline '{
specific_finish_beamline
}'
##############################################################################
# backwards compatibility macros... should be tidied up and removed
# after testing that we can live without them!
#
#
def prodc_quick_realign '{
global curr_intensity start_intensity
start_intensity = curr_intensity
curr_intensity = 0
check_beam()
shopen
specific_quick_realign
shclose
}'
def prodc_normal_realign '{
global curr_intensity start_intensity
start_intensity = curr_intensity
curr_intensity = 0
shopen
specific_normal_realign
shclose
}'
def prodc_open_safety_shutter '{
print "reference to old command prodc_open_safety_shutter, redirected to shopen"
shopen
}'
def prodc_close_safety_shutter '{
print "reference to old command prodc_close_safety_shutter, redirected to shclose"
shclose
}'
def open_ms_shutter '{
print "reference to old command open_ms_shutter, redirected to msopen"
msopen
}'
def close_ms_shutter '{
print "reference to old command close_ms_shutter, redirected to msclose"
msclose
}'
#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% BLISS
#$Revision: 1.62 $$Date: 2013/08/19 12:38:35 $
#%END%
#%LOG%
#$Log: mxcollect.mac,v $
#Revision 1.62 2013/08/19 12:38:35 beteva
#Added local_skip_images
#
#Revision 1.61 2011/11/08 15:52:13 guijarro
#removed check for overlap with helical, non needed anymore
#
#Revision 1.60 2010/06/29 16:36:43 beteva
#added check for overlap and position when helical oscillation
#
#Revision 1.59 2010/06/04 06:43:43 guijarro
#added code for moving motors specified in comment field
#
#Revision 1.58 2010/05/17 12:43:13 guijarro
#added code for not closing safety shutter while in the middle of a queue
#
#Revision 1.57 2010/03/29 07:49:39 guijarro
#adapted to latest version of beamline parameters
#
#Revision 1.55 2010/02/16 15:32:09 spruce
#Change the inverse beam flag. This was changed at some point in mxcube, probably to reflect the same terminology used in the ISPyB enumerated record entry.
#This broke the inverse beam option because spec no longer recognised it.
#
#Revision 1.54 2010/02/09 15:54:17 blissadm
#adapted to latest mxutils.mac
#
#Revision 1.53 2009/11/05 14:39:54 spruce
#corrected the simulated ccdflush so the adsc suffix is added to the last image
#
#Revision 1.52 2009/04/06 15:28:28 guijarro
#added test to find if we have a microdiff or a minidiff
#
#Revision 1.51 2009/04/02 08:35:41 guijarro
#added warning message for HELICAL_OSCIL
#load MUSST program
#
#Revision 1.47 2008/07/28 12:20:42 guijarro
#do not execute prodc_set_mono if energy change is less than 2 eV
#
#Revision 1.46 2008/07/09 15:15:08 guijarro
#added check_beam before quick realign
#
#Revision 1.45 2008/06/24 15:56:04 spruce
#make gain adjustment for autogain
#
#Revision 1.44 2008/03/25 12:46:40 blissadm
#if egui_fatal is called also set the log message variable.
#
#Revision 1.43 2008/02/18 17:15:45 spruce
#bug fixes following test of waitforbeam
#to enable this feature set the global I0THRESHOLD in the setup
#
#Revision 1.42 2008/01/17 16:41:13 blissadm
#added halfcorner calculation, just in case we want to display it in mxcube
#
#Revision 1.40 2007/12/03 16:14:04 spruce
#add a waitmove before ccdstart to be sure that any spindle movements are finished. This solves a problem of image smearing for adsc Q210/315 detectors where teh dark time is sensitive to the integration time.
#
#Revision 1.39 2007/10/31 14:51:00 guijarro
#added CURRENT_FRAME_NUMBER global variable (mainly for microdiff)
#
#Revision 1.38 2007/10/03 13:04:47 spruce
#added methods for storing undulator gaps, kappa positions, beam size/divergence/polarisation in the database. kappSpecMne and phiSpecMne should be defined as beamline parameters as motors in mxlocal as undulatorGap0, 1, 2 depending on the number of undulators. Currently nothing is returned for beamsize/divergence etc until further information is given by the mx group.
#
#Revision 1.37 2007/05/22 13:17:34 gabadinh
#Had to preempt the error message before calling SCMinidiffGetControl because this macro does an exit if something goes wrong...
#
#Revision 1.36 2007/05/22 11:56:14 gabadinh
#Renamed the variable/channel eprodc_fatal_message to eprodc_fatal_collect, also from string to an associative-array; it is also cleared at the beggining of every data collection
#
#Revision 1.35 2007/05/11 15:03:32 gabadinh
#added several beamline values to the data collection macro return associative-array:
#-transmission
#-resolution
#-detector distance
#-wavelength
#-beam centre
#
#Revision 1.34 2007/03/30 13:44:07 gabadinh
#prodc_prepare_beamline moves some minidiff motors to the centred position, if defined in the parameters
#
#Revision 1.33 2007/03/06 08:34:34 guijarro
#refactoring + added fatal log function
#
#Revision 1.32 2007/01/22 16:28:26 guijarro
#added special order when modifying CURRENT_IMAGE,
#this is very important for mxCuBE
#
#Revision 1.31 2007/01/18 15:04:56 spruce
#a few changes to make the test_mxcollect work again
#
#Revision 1.30 2007/01/18 13:12:41 spruce
#change CURRENT_IMAGE global from string to array
#
#Revision 1.29 2007/01/18 12:37:47 spruce
#took away phi cleanup code and call the phi cleanup in oscilPX directly
#
#Revision 1.28 2006/12/14 16:29:40 guijarro
#makes sure that phi motor get its speed & velocity back to normal
#in the cleanup
#
#Revision 1.27 2006/12/07 17:17:34 spruce
#added code to stop data collection elegantly in the middle of a wedge
#
#Revision 1.26 2006/12/06 16:05:17 spruce
#corrections for stills after testing on ID14-2
#
#Revision 1.24 2006/11/28 16:45:54 spruce
#inverse beam flag changed in mxcube, made compatible in this version
#
#Revision 1.23 2006/11/21 16:41:19 spruce
#change format of integrated counts to %g
#
#Revision 1.22 2006/10/09 09:30:17 spruce
#add a dummy definition of the hook to save it being created in all local
#macros. This means the local definition must be placed to overload the dummy
#macro when spec starts
#
#Revision 1.21 2006/10/03 13:33:15 spruce
#>> a little clean up. This has been running for 4 days on ID14-4 including pipeline demos and users. No detector problems reported.
#return code changed back to 2005 to remove warning in mxCuBE
#
#Revision 1.20 2006/09/28 15:36:04 spruce
#bugs fixed, compatible with mxadsc 1.17
#
#Revision 1.19 2006/09/27 13:26:30 spruce
#open the safety shutter after darks
#make the automatic gain adjustment of the amplifiers
#
#Revision 1.18 2006/09/26 12:47:57 spruce
#pick up detector errors and abort if necessary
#added generic hook to do specific calculations e.g for best and raddose.
#
#Revision 1.17 2006/09/12 12:55:06 guijarro
#no more call ccdcleanup in cleanup : this will be done when
#necessary by adsc macros (in mxadsc.mac).
#
#Revision 1.16 2006/08/24 16:45:56 gabadinh
#reads default_number_of_passes from MxBcmPars, not from MxCollectPars
#commented out the current detector binning mode
#
#Revision 1.15 2006/08/24 12:28:04 blissadm
#added default exposure time to list of vars for mxCuBE. needs to be added to mxlocal.xml.
#removed setting of detector mode to the default. new check to verify if the requested binning mode is equal to the default.
#
#Revision 1.14 2006/07/28 15:29:52 guijarro
#bug fix with overlap when 'skip images' was ON ;
#added call to prodc_finish_beamline in cleanup,
#and call datacollection_cleanup instead of shclose
#and prodc_finish_beamline at the end of data collection.
#
#Revision 1.13 2006/07/11 14:11:54 spruce
#fixes for validating collect parameters
#
#Revision 1.12 2006/07/10 15:37:02 guijarro
#fixed call to setMxSpecPars
#
#Revision 1.11 2006/07/05 15:18:04 spruce
#added new validation check for overlap=1
#
#Revision 1.10 2006/06/14 08:45:04 gabadinh
#added backlash while checking the limits of detector distance motor
#added moving the detector if distance is given
#
#Revision 1.9 2006/06/06 14:16:50 spruce
#add suffix to imagefile variable
#
#Revision 1.8 2006/05/31 16:08:06 spruce
#added new parameters for phi_speed, exposure time default number of passes
#to update_collect_parameters function for xmCuBE and DNA
#
#Revision 1.7 2006/05/15 11:41:26 spruce
#bugfix DNA sends resolution with the upper keyword instead of lower
#new function validate_collect_parameters to filter user mistakes
#
#Revision 1.6 2006/05/11 11:43:20 spruce
#small bug, dark fixed to on every time
#
#Revision 1.5 2006/05/03 15:26:43 spruce
#added limit checking if trying to move detector out of limits
#
#Revision 1.4 2006/04/11 14:08:27 guijarro
#bug fix for "skip images" feature :
#the filename given to the file_info function was incomplete (missing extension)
#
#Revision 1.3 2005/11/20 18:20:10 blissadm
#new code with inverse beam functionality
#
#Revision 1.2 2005/11/08 17:31:28 beteva
#added some COLLECT_PARS for the dark time calculations
#
#Revision 1.1 2005/11/08 17:26:20 beteva
#Initial revision
|