#$Log: take_powders.mac,v $
#Revision 1.25 2009/02/09 16:27:54 beteva
#changed _oscillation_prepare to osc_prepare and _oscillation to osc_scan to be able to use the same macro set with the microdiff
#
#Revision 1.24 2007/09/19 09:16:05 spruce
#archive directory for copying succesful powder calibrations changed from /data/idxxehx/archive to /data/pyarch/idxxehx/POWDERS
#
#Revision 1.23 2007/09/03 15:28:07 guijarro
#waitmove replaced by move_poll,
#RMSD value changed to 0.025
#
#Revision 1.22 2007/04/23 08:03:29 spruce
#add print to show where the powder files are being copied
#
#Revision 1.21 2007/01/26 16:16:05 spruce
#copy the powder.log to the archive (if successful) as well as images and xml file
#
#Revision 1.20 2006/10/06 14:55:32 spruce
#It occurred to me that we only want to copy successful powder runs to the archive, not all of them.
#
#Revision 1.19 2006/09/28 15:33:11 spruce
#from id29, only that the resulting archive images go to a dated directory
#
#Revision 1.17 2006/09/22 10:03:56 spruce
#process images in the inhouse directory, only copy results to the archive
#wait for the last image to appear on disk before processing
#
#Revision 1.16 2006/09/20 13:43:35 spruce
#added newline at end of file to powder.inp to fix bug in xml file generation
#.
#
#Revision 1.15 2006/09/07 10:22:16 guijarro
#compare distances with user values
#
#Revision 1.14 2006/07/11 14:10:51 spruce
#changed flag dark to TakeDarkFlag to be compatible with other macros
#
#Revision 1.13 2006/07/06 15:06:05 spruce
#corrections to process_results
#
#Revision 1.12 2006/07/05 13:08:01 blissadm
#new take powders which processes results and puts them back in the new mxlocal.xml file if they meet the requirements. Depends on new functions in xmlutils and mxutils
#
#Revision 1.11 2006/07/03 12:24:03 spruce
#new function process results is called after running the powder program.
#This generates the mxPowderCalibration results in the HardwareRep dir
#Changes are necessary in the mxutils(3.6) to use this file (or the mxlocal derived from it also in the HardwareRep dir)
#
#Revision 1.10 2006/06/15 12:28:46 guijarro
#remove suffix being added to detector files names (the filename should include the suffix directly)
#
#Revision 1.9 2006/05/11 12:28:00 spruce
#many changes for mxutils compatiblity
#
#Revision 1.8 2006/05/09 12:46:24 spruce
#forgot to change prodc_open/close_safety_shutter to shopen/shclose!
#
#Revision 1.7 2006/05/09 12:42:15 spruce
#one collect_par missed (for setting the darks on)
#
#Revision 1.6 2006/04/10 14:17:32 guijarro
#replaced collect_par with setMxSpecPars
#
#Revision 1.5 2006/03/07 13:30:07 beteva
#bug corrected; test for q4r added;
#
#Revision 1.4 2006/02/24 17:02:42 beteva
#added copying to the archive directory. Changes the setup parameters. Cleanup.
#
#Revision 1.3 2006/02/10 11:24:50 guijarro
#new version
#
#Revision 1.1 2005/04/15 15:23:50 beteva
#Initial revision
#
#%TITLE% TAKE_POWDERS.MAC
#%NAME% %B%take_powders.mac%B% - set of macros to take powders image
#%DESCRIPTION%
#%END%
#%UU% ()
#%MDESC% Init generic parameters
def powders_init() '{
global PDR_SUPPORTED_FORMATS[] PDR_POWDERPROG
global PDR_MSG[] PDR_DETMNE PDR_DET PDR_OK
global PDR_PHI_START PDR_PHI_STOP PDR_EXPOSURE
local type format
PDR_SUPPORTED_FORMATS["q4"]="Q4unbin"
PDR_SUPPORTED_FORMATS["q210"]="Q210bin"
PDR_SUPPORTED_FORMATS["q315"]="Q315bin"
PDR_SUPPORTED_FORMATS[165]="MCCD165"
PDR_SUPPORTED_FORMATS[133]="MCCD133"
PDR_SUPPORTED_FORMATS["mar225"]="MAR225"
PDR_POWDERPROG = "/opt/pxsoft/bin/powder"
PDR_DET = MXBCM_PARS["detector"]["type"]
if (PDR_DET == "adsc") {
type = MXBCM_PARS["detector"]["model"]
if (index(type,"q4") != 0) {
type = "q4"
#force the mode to unbinned
setMxSpecPars([0:"detector", 1:"binning"], 1)
} else {
#force the mode to hwbinned
setMxSpecPars([0:"detector", 1:"binning"], 2)
}
} else if (PDR_DET == "marccd") {
type = MXBCM_PARS["detector"]["model"]
} else
type = "mar225"
format = PDR_SUPPORTED_FORMATS[type]
PDR_DETMNE = getMxSpecPars("detdistmot")
PDR_MSG["FORMAT"] = sprintf ("FORMAT %s\n", format)
PDR_MSG["DVALUES"] = "DVALUES 3.645 2.672 2.487 2.181 1.819 1.676 1.467 1.433\n"
PDR_MSG["DSTART"] = "DSTART 0.00001 0.1 0.1 0.0002 0.1 0.1 0.001 0.1 0.001\n"
PDR_MSG["TOLERANCE"] = "TOLERANCE 0.0001\n"
# the name of the xml file that will be generated by the powder program
PDR_MSG["XMLFILE"] = "XMLFILE mxPowderCalibration.xml"
PDR_PHI_START = 0
PDR_PHI_STOP = 1
PDR_EXPOSURE = 1
PDR_OK = 0
}'
#%UU% [det_mne phi_start phi_end exp_time det_dev powder_prog]
#%MDESC% Define the %B%det_mne%B% - detector motor mnemonic, the spindle
#%B%phi_start%B% and %B%phi_stop%B% angle, the %B%exp_time%B%, the detector
#device server name %B%det_dev%B% and %B%powder_prog%B% - the name of the
#computation program.
def powders_setup '{
global PDR_DETDEV PDR_FIRST PDR_LAST PDR_LOCALDIR PDR_TUNE
global PDR_DETMOT PDR_DISTNB
global PDR_PREFIX PDR_DIR PDR_ADIR
local fn[] i lim lfirst llast res sign ldir
powders_init()
if ($# < 4) {
PDR_DETDEV = getval("Detector device server name (e.g. id29/adsc/1):", PDR_DETDEV)
PDR_FIRST = getval("Initial detector distance [mm]:", PDR_FIRST)
PDR_LAST = getval("End detector distance [mm]:", PDR_LAST)
PDR_LOCALDIR = getval("Data beamline directory, as mounted (e.g. id14eh1):", PDR_LOCALDIR)
PDR_TUNE = yesno("Further setup", PDR_TUNE)
if (PDR_TUNE) {
PDR_PHI_START = getval("Phi start angle:", PDR_PHI_START)
PDR_PHI_STOP = getval("Phi stop angle:", PDR_PHI_STOP)
PDR_EXPOSURE = getval("Exposure time [s]:", PDR_EXPOSURE)
}
} else if ($# >= 4) {
PDR_DETDEV = "$1"
PDR_FIRST = $2
PDR_LAST = $3
PDR_LOCALDIR = "$4"
if ($# > 4) {
PDR_PHI_START = $5
PDR_PHI_STOP = $6
PDR_EXPOSURE = $7
}
}
PDR_DETMOT = motor_num(PDR_DETMNE)
if (PDR_DETMOT == -1) {
eprintf ("Detector distance motor %s not configured, please change the name\n", PDR_DETMNE)
PDR_OK = -1
}
if (PDR_FIRST > PDR_LAST) {
lfirst = PDR_LAST
llast = PDR_FIRST
sign = -1
} else {
lfirst = PDR_FIRST
llast = PDR_LAST
sign = 1
}
lim = user(PDR_DETMOT, get_lim(PDR_DETMOT, -1))
if (lim > lfirst) {
eprintf ("Distance %g lower than the motor limit %g, please change it\n", lfirst, lim)
PDR_OK = -1
}
lim = user(PDR_DETMOT, get_lim(PDR_DETMOT, 1))
if (lim < llast) {
eprintf ("Distance %g higher than the motor limit %g, please change it\n", llast, lim)
PDR_OK = -1
}
unglobal PDR_DETDIST
global PDR_DETDIST[]
if (PDR_OK != -1) {
res = fabs(PDR_LAST - PDR_FIRST)
PDR_DISTNB = int(res/25)
PDR_DETDIST[0] = PDR_FIRST
if ((res%25) != 0) {
PDR_DISTNB += 1
}
PDR_DETDIST[PDR_DISTNB] = PDR_LAST
} else
PDR_DISTNB = 0
if (PDR_DISTNB == 0) {
eprintf ("powders_setup: Distances not set !\n")
PDR_OK = -1
}
PDR_DIR = sprintf("/data/%s/inhouse", PDR_LOCALDIR)
if ((file_info(PDR_DIR,"isdir") == 0) || (file_info(PDR_DIR,"-w") == 0)) {
eprintf ("Directory %s is not writable, setup failed\n", PDR_DIR)
PDR_OK = -1
PDR_DIR = ""
}
PDR_ADIR = sprintf("/data/pyarch/%s/POWDERS",PDR_LOCALDIR)
if ((file_info(PDR_ADIR,"isdir") == 0) || (file_info(PDR_ADIR,"-w") == 0)) {
if (file_info(PDR_ADIR,"-e") == 0) {
if (unix(sprintf("mkdir %s",PDR_ADIR)) == -1) {
eprintf ("Cannot create %s directory\n", PDR_ADIR)
PDR_OK = -1
}
} else {
eprintf ("Directory %s is not writable, setup failed\n", PDR_DIR)
PDR_OK = -1
PDR_ADIR = ""
}
}
if (PDR_OK != -1) {
for (i=1; i<PDR_DISTNB; i++)
PDR_DETDIST[i] = PDR_DETDIST[i-1] + 25*sign
PDR_DISTNB += 1
printf ("%d images will be taken from %d to %d, every 25 mm\n", \
PDR_DISTNB, PDR_DETDIST[0], PDR_DETDIST[PDR_DISTNB-1])
PDR_OK = 0
}
}'
#%IU%
#%MDESC% Cleanup procedure.
def powders_cleanup '{
local msg
printf("powder collect cleanup initiated")
msg = sprintf("---- Collect Powders Aborted on %s ----", date())
egui_logmsg(msg)
msclose
ccdcleanup
shclose
exit
}'
def create_dir(ldir) '{
local fn fulldir ret
split(date(),fn)
fulldir = sprintf("%s/%s%s%s",ldir,fn[2],fn[1],fn[4])
if (file_info(fulldir) == 0) {
if (unix(sprintf("mkdir %s",fulldir)) == -1) {
eprintf ("Cannot create %s directory\n", fulldir)
fulldir = ""
}
}
PDR_PREFIX = sprintf("powder_%s%s", fn[2],fn[1])
return(fulldir)
}'
#%IU%
#%MDESC% Collect process the images
def collect_powders() '{
unglobal COLLET_SEQ
global COLLECT_SEQ
local cmd ihdir ardir
if (PDR_OK == 0) {
if ((ihdir = create_dir(PDR_DIR)) == "") {
eprintf ("error in configuration, procedure not executed\n")
return(-1)
}
if ((ardir = create_dir(PDR_ADIR)) == "") {
eprintf ("error in configuration, procedure not executed\n")
return(-1)
}
backin
lightout
COLLECT_SEQ["fileinfo"]["prefix"] = PDR_PREFIX
COLLECT_SEQ["fileinfo"]["directory"] = ihdir
COLLECT_SEQ["fileinfo"]["run_number"] = 1
COLLECT_SEQ["start"] = PDR_PHI_START
COLLECT_SEQ["range"] = PDR_PHI_STOP - PDR_PHI_START
COLLECT_SEQ["exposure_time"] = PDR_EXPOSURE
COLLECT_SEQ["number_of_passes"] = 1
COLLECT_SEQ["start_image_number"] = 0
take_images(COLLECT_SEQ, PDR_DETMOT)
process_images(ihdir, PDR_PREFIX, REAL_DIST)
}
}'
#%IU% (collect_seq, det_mot)
#%MDESC% Collect PDR_DISTNB number of images. Write them in the %B%dir%B%
#directory.
def take_images(tp_pars, det_mot) '{
local i msg end_ang
unglobal REAL_DIST
global REAL_DIST[]
cdef("cleanup_once","powders_cleanup;","_powders")
# force darks
setMxCollectPars("TakeDarkFlag",1)
msg = sprintf ("---- Collect Powders Beam Calibration procedure started on %s ----", date())
egui_logmsg(msg)
egui_logmsg("Current configuration: (to change type powders_setup in spec)")
msg = sprintf (" File: %s/%s\n", dir, prefix)
msg = sprintf ("%sPhi Start/Stop: %g - %g degrees\n", msg, tp_pars["start"], tp_pars["start"]+tp_pars["range"])
msg = sprintf ("%s Exposure time: %g seconds, 1 pass\n", msg, tp_pars["exposure_time"])
egui_logmsg(msg)
ccdprep(getMxCollectPars("dark"),tp_pars["start"],tp_pars["range"],tp_pars["exposure_time"],tp_pars["number_of_passes"],tp_pars["comment"])
shopen
for (i=0;i<PDR_DISTNB;i++) {
egui_logmsg(sprintf("Collecting powder at %6.3f mm...",PDR_DETDIST[i]))
printf("Moving detector to %g\n", PDR_DETDIST[i])
A[det_mot] = PDR_DETDIST[i]
move_em; move_poll; get_angles
beam_centre_update()
printf("Image %d\n", i+1)
REAL_DIST[i] = A[det_mot]
ccdprep(getMxCollectPars("TakeDarkFlag"),tp_pars["start"],tp_pars["range"],tp_pars["exposure_time"],tp_pars["number_of_passes"],tp_pars["comment"])
ccdfile(tp_pars,PDR_DETDIST[i])
ccdstart
end_ang = tp_pars["start"] + tp_pars["range"]
osc_prepare tp_pars["start"] end_ang tp_pars["exposure_time"] 1
osc_scan tp_pars["start"] end_ang tp_pars["exposure_time"] 1
ccdread
if (i == (PDR_DISTNB-1)) {
ccdflush
} else {
ccdsave 0
}
}
shclose
# wait for the last image to be written an error will be generated later on if it times out
tout = 10
printf("Waiting for %s to appear on disk",ccdfile(tp_pars,PDR_DETDIST[i-i]))
while (file_info(ccdfile(tp_pars,PDR_DETDIST[i-i]) != 1) && tout>0) {
sleep(1); tout -=1
}
}'
#%IU% (dir, prefix, dist)
#%MDESC% Process the %B%prefix%B%.img images in the %B%dir%B% directory, for
#the %B%dist%B% detector distances.
def process_images(dir,prefix,dist) '{
global COLLECT_SEQ
local i, file, tp_pars
tp_pars = COLLECT_SEQ
file = sprintf("%s/%s",dir,"powder.inp")
# remove previous input file if it exists
unix(sprintf("rm -f %s",file))
if (open(file)) return (0)
fprintf(file,">powder.inp created at beamline %s on %s\n",beamline,date())
fprintf(file, PDR_MSG[0])
for (i=0; i<PDR_DISTNB; i++) {
tp_pars["fileinfo"]["directory"] = dir
tp_pars["fileinfo"]["prefix"] = prefix
current_filename = ccdfile(tp_pars,PDR_DETDIST[i])
fprintf(file,"POWDER %s %6.3f\n",current_filename,dist[i])
}
fprintf (file, PDR_MSG["FORMAT"])
fprintf (file, PDR_MSG["DVALUES"])
inp[0] = "beam"
inp[1] = "bx"
bxbeam = getMxSpecPars(inp)
inp[1] = "ax"
axbeam = getMxSpecPars(inp)
inp[1] = "by"
bybeam = getMxSpecPars(inp)
inp[1] = "ay"
aybeam = getMxSpecPars(inp)
PDR_MSG["START"] = sprintf("START %5.4f 0.0 0.0 1.000 0.0 %6.2f %7.4f %6.2f %7.4f\n", \
getMxWavelength(),bxbeam,axbeam,bybeam,aybeam)
fprintf(file, PDR_MSG["START"])
fprintf(file, PDR_MSG["DSTART"])
fprintf(file, PDR_MSG["TOLERANCE"])
fprintf(file, PDR_MSG["XMLFILE"] )
fprintf(file, "\n" )
close(file)
egui_logmsg(sprintf("Processing results (see %s/powder.log)",dir))
cmd = sprintf("cd %s; %s < %s/powder.inp > %s/powder.log", dir, PDR_POWDERPROG, dir, dir)
printf ("executing.. %s\n", cmd)
unix(cmd)
if (process_results(dir) == -1 ) {
msg = sprintf("---- Collect Powders Beam Calibration procedure failed, calibration not updated on %s---",date())
print msg; egui_logmsg(msg)
} else {
msg = sprintf("---- Collect Powders Beam Calibration procedure completed on %s ----",date())
print msg; egui_logmsg(msg)
}
}'
def process_results(dir) '{
# read the output xml file
local xmlfile[]
xmlfile[0]=""
split(PDR_MSG["XMLFILE"],xmlfile," ")
xmlname = substr(xmlfile[1],0,index(xmlfile[1],".")-1)
if (xml_readProperties(sprintf("../../../..%s/%s",dir,xmlname)) == -1) {
printf("Error getting results from powder program xml output: (%s)",XML_tmp["__error__"])
return(-1)
}
imagesAsked = XML_tmp["numberOfInputImagesAsked"]["__value__"]
imagesRead = XML_tmp["numberOfInputImagesRead"]["__value__"]
if (imagesRead != imagesAsked) {
msg = sprintf("Problem with powder analysis, images read by program (%d) did not equal images taken (%d)\n",imagesRead,imagesAsked)
print msg; egui_logmsg(msg)
return(-1)
}
if (XML_tmp["percentageOfIndexedSpots"]["__value__"] < 50) {
msg = sprintf("Error: Number of indexed spots below 50% (%6.3f)",XML_tmp["percentageOfIndexedSpots"]["__value__"])
print msg; egui_logmsg(msg)
return(-1)
}
if (XML_tmp["rmsd"]["__value__"] > 0.0025) {
msg = sprintf("Error: RMSD is greater than 0.0025\n")
print msg; egui_logmsg(msg)
return(-1)
}
if(xml_readProperties(sprintf("../../../..%s/%s",dir,xmlname),"/*/refinedBeamCentreCalibration")==-1) {
printf("Error getting results from powder program xml output: (%s)",XML_tmp["__error__"])
return(-1)
}
MXSPEC_PARS["beam"]["ax"] = XML_tmp["xbeam_a"]["__value__"]
MXSPEC_PARS["beam"]["ay"] = XML_tmp["ybeam_a"]["__value__"]
MXSPEC_PARS["beam"]["bx"] = XML_tmp["xbeam_b"]["__value__"]
MXSPEC_PARS["beam"]["by"] = XML_tmp["ybeam_b"]["__value__"]
print "all ok, updating calibration..."
local_pars_commit()
# the result was successful so copy it to the archive
# copy the results to the archive, leaving the rest behind in the inhouse directory
adir=create_dir(PDR_ADIR)
cmd = sprintf("cp %s/powder_* %s/*.xml *.log %s", dir,dir, adir)
printf("Copy to archive- %s\n",cmd)
ret = unix(cmd)
return(0)
}'
#%IU%
#%MDESC% Macro called by ProDC
def beam_calibration '{
collect_powders()
}'
#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% BLISS (A.Beteva/D.Spruce/M.Guijarro)
#$Revision: 1.25 $ $Date: 2009/02/09 16:27:54 $
|