def run(cbf_files, params): print "Attention - assuming cbf files given belong to a single dataset" print print "%d cbf files were given." % len(cbf_files) print if params.byteoffset: import yamtbx_byteoffset_h5_ext import pyublas last_shape = easy_mp.pool_map(fixed_func=lambda x: convert(x, params), args=cbf_files, processes=params.nproc)[-1] if params.decompose: make_geom_decomposed( XIO.Image(cbf_files[0]).header, last_shape, params.geom_out) else: make_geom(XIO.Image(cbf_files[0]).header, params.geom_out) make_beam(params.beam_out) print "Done." print print "Check %s and %s!" % (params.geom_out, params.beam_out)
def takeout_datasets(img_template, min_frame, max_frame, _epsilon=1e-5, check_wavelength=True, check_distance=True, check_oscwidth=True): img_indexes = [] wavelengths = [] distances = [] start_angles = [] end_angles = [] ang_widths = [] filenames = [] img_files = template_to_filenames(img_template, min_frame, max_frame) # Read header for i, f in enumerate(img_files): if os.path.isfile(f): try: im = XIO.Image(f) except Exception, ex: print "Error on reading", f print traceback.format_exc() return [] start_angles.append( im.header["PhiStart"] ) end_angles.append( im.header["PhiEnd"] ) ang_widths.append( im.header["PhiWidth"] ) wavelengths.append( im.header["Wavelength"] ) distances.append( im.header["Distance"] ) img_indexes.append(min_frame+i) filenames.append(f)
def is_dataset(img_template, min_frame, max_frame, _epsilon=1e-5, quiet=False): """ Check whether image files belong to single dataset - Successive oscillation (missing frames OK) - Identical wavelength, distance """ img_indexes = [] wavelengths = [] distances = [] start_angles = [] end_angles = [] ang_widths = [] filenames = [] img_files = template_to_filenames(img_template, min_frame, max_frame) # Read header for i, f in enumerate(img_files): if os.path.isfile(f): try: im = XIO.Image(f) except Exception, ex: if not quiet: print traceback.format_exc() return False start_angles.append( im.header["PhiStart"] ) end_angles.append( im.header["PhiEnd"] ) ang_widths.append( im.header["PhiWidth"] ) wavelengths.append( im.header["Wavelength"] ) distances.append( im.header["Distance"] ) img_indexes.append(i+1) filenames.append(f)
def convert(cbfin, params): if params.byteoffset: import yamtbx_byteoffset_h5_ext import pyublas h5out = os.path.basename(cbfin) + ".h5" data, ndimfast, ndimmid = cbf.load_minicbf_as_numpy(cbfin) data = data.reshape((ndimmid, ndimfast)) if params.decompose: data = decompose_panels(data) header = XIO.Image(cbfin).header of = h5py.File(h5out, "w") grp = of.create_group("LCLS") dset = grp.create_dataset("photon_energy_eV", (1, ), dtype=numpy.float) dset[...] = 12398.4 / header["Wavelength"] dset = grp.create_dataset("photon_wavelength_A", (1, ), dtype=numpy.float) dset[...] = header["Wavelength"] dset = grp.create_dataset("adu_per_eV", (1, ), dtype=numpy.float) dset[...] = header["Wavelength"] / 12398.4 dset = grp.create_dataset("detector_distance_m", (1, ), dtype=numpy.float) dset[...] = header["Distance"] / 1000. dset = grp.create_dataset("beam_xy_px", (2, ), dtype=numpy.float) dset[...] = (header["BeamX"] / header["PixelX"], header["BeamY"] / header["PixelY"]) dset = grp.create_dataset("osc_step_deg", (1, ), dtype=numpy.float) dset[...] = header["PhiWidth"] cbfin = os.path.abspath(cbfin) dset = grp.create_dataset("original_file", (1, ), "S%d" % len(cbfin)) dset[...] = cbfin grp = of.create_group("data") if params.byteoffset: assert data.dtype == numpy.int32 # hid_t group_id, const std::string &name, const pyublas::numpy_vector<int> &data, int width, int height) yamtbx_byteoffset_h5_ext.write_byteoffset_data(grp.id.id, "data", data.ravel(), data.shape[1], data.shape[0]) else: dset = grp.create_dataset("data", data.shape, dtype=data.dtype) #, compression="CBF") dset[...] = data of.close() print "Processed: %s" % os.path.basename(cbfin) return data.shape
def timestamps(img_files): img_date = [] for f in img_files: im = XIO.Image(f) img_date.append((f, im.header["DateSeconds"])) for i in xrange(len(img_files)): print img_files[i], if i == 0: print 0 else: print img_date[i][1] - img_date[i - 1][1]
def find_data_sets(wdir, skip_symlinks=True, skip_0=False, split_hdf_miniset=True): """ Find data sets in wdir """ img_files = find_img_files(wdir, skip_symlinks=skip_symlinks) img_files.sort() h5files = filter(lambda x:x.endswith(".h5"), img_files) ret = [] # group images group = group_img_files_template(img_files, skip_0=skip_0) print group for img_template, min_frame, max_frame in group: if min_frame == max_frame: continue for minf, maxf in takeout_datasets(img_template, min_frame, max_frame): ret.append([img_template, minf, maxf]) for f in h5files: try: im = XIO.Image(f) except: print "Error on reading", f print traceback.format_exc() continue if not split_hdf_miniset: ret.append([f.replace("_master.h5","_??????.h5"), 1, im.header["Nimages"]]) continue for i in xrange(im.header["Nimages"]//im.header["Nimages_each"]+1): nr0, nr1 = im.header["Nimages_each"]*i+1, im.header["Nimages_each"]*(i+1) if nr1 > im.header["Nimages"]: nr1 = im.header["Nimages"] ret.append([f.replace("_master.h5","_??????.h5"), nr0, nr1]) if nr1 == im.header["Nimages"]: break return ret
def shorten_frame_range_if_missing(img_template, nr1, nr2): if "_??????.h5" in img_template: nr1 = max(nr1, 1) try: im = XIO.Image(img_template.replace("_??????.h5", "_master.h5")) nr2 = min(nr2, im.header["Nimages"]) except: print "Error on reading", img_template print traceback.format_exc() nr1 = nr2 = 0 else: files = glob.glob(img_template) if files: numbers = sorted(map(lambda x: int(x[img_template.index("?"):img_template.rindex("?")+1]), files)) nr1 = max(nr1, numbers[0]) nr2 = min(nr2, numbers[-1]) else: nr1 = nr2 = 0 return nr1, nr2
def generate_xds_inp(img_files, inp_dir, reverse_phi, anomalous, spot_range=None, minimum=False, crystal_symmetry=None, integrate_nimages=None, osc_range=None, orgx=None, orgy=None, rotation_axis=None, distance=None, wavelength=None, minpk=None, exclude_resolution_range=[], fstart=None, fend=None, extra_kwds=[]): is_eiger_hdf5 = (len(img_files) == 1 and "_master.h5" in img_files[0]) if is_eiger_hdf5: template = img_files[0].replace("_master.h5", "_??????.h5") else: groups = group_img_files_template(img_files) assert len(groups) == 1 template, fstart, fend = groups[ 0] # arguments fstart, fend are overwritten here #print inp_dir, img_files[0], template tmp = [ os.path.dirname(os.path.relpath(img_files[0], inp_dir)), os.path.dirname(os.path.abspath(img_files[0])) ] imdir = min(tmp, key=lambda x: len(x)) template = os.path.join(imdir, os.path.basename(template)) #print imdir im = None for imgfile in img_files: if os.path.isfile(imgfile): im = XIO.Image(imgfile) break if im is None: raise Exception("No actual images found.") if crystal_symmetry is None: sgnum = 0 cell_str = "50 60 70 90 90 90" else: sgnum = crystal_symmetry.space_group_info().type().number() cell_str = " ".join( map(lambda x: "%.2f" % x, crystal_symmetry.unit_cell().parameters())) if osc_range is None: osc_range = im.header["PhiWidth"] data_range = "%d %d" % (fstart, fend) if spot_range is None: spot_range = "%d %d" % (fstart, (fend + fstart) / 2) elif spot_range == "first": spot_range = "%d %d" % (fstart, fstart) elif spot_range == "all": spot_range = "%d %d" % (fstart, fend) elif len(spot_range) == 2: spot_range = "%d %d" % spot_range else: print "Error!" return if rotation_axis is None: if im.header["ImageType"] == "raxis": rotation_axis = (0, 1, 0) else: rotation_axis = (1, 0, 0) if reverse_phi: rotation_axis = map(lambda x: -1 * x, rotation_axis) rotation_axis = " ".join(map(lambda x: "%.2f" % x, rotation_axis)) if integrate_nimages is None: delphi = 5 else: delphi = osc_range * integrate_nimages nx, ny = im.header["Width"], im.header["Height"], qx, qy = im.header["PixelX"], im.header["PixelY"] if orgx is None: orgx = im.header["BeamX"] / qx if orgy is None: orgy = im.header["BeamY"] / qy if wavelength is None: wavelength = im.header["Wavelength"] if distance is None: distance = im.header["Distance"] friedel = "FALSE" if anomalous else "TRUE" sensor_thickness = 0 # FIXME if im.header["ImageType"] == "marccd": detector = "CCDCHESS MINIMUM_VALID_PIXEL_VALUE= 1 OVERLOAD= 65500" elif im.header["ImageType"] == "raxis": detector = "RAXIS MINIMUM_VALID_PIXEL_VALUE= 0 OVERLOAD= 2000000" distance *= -1 elif im.header["ImageType"] == "minicbf": detector = "PILATUS MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD= 1048576" sensor_thickness = sensor_thickness_from_minicbf(img_files[0]) elif im.header["ImageType"] == "adsc": detector = "ADSC MINIMUM_VALID_PIXEL_VALUE= 1 OVERLOAD= 65000" elif im.header["ImageType"] == "mscccd": detector = "SATURN MINIMUM_VALID_PIXEL_VALUE= 1 OVERLOAD= 262112" # XXX Should read header!! distance *= -1 elif is_eiger_hdf5: detector = "EIGER MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD= %d" % im.header[ "Overload"] sensor_thickness = im.header["SensorThickness"] if minpk is not None: extra_kwds.append(" MINPK= %.2f" % minpk) for r1, r2 in exclude_resolution_range: if r1 < r2: r1, r2 = r2, r1 extra_kwds.append(" EXCLUDE_RESOLUTION_RANGE= %.3f %.3f" % (r1, r2)) extra_kwds = "\n".join(extra_kwds) inp_str = """\ JOB= XYCORR INIT COLSPOT IDXREF DEFPIX INTEGRATE CORRECT ORGX= %(orgx).2f ORGY= %(orgy).2f DETECTOR_DISTANCE= %(distance).2f OSCILLATION_RANGE= %(osc_range).3f X-RAY_WAVELENGTH= %(wavelength).5f NAME_TEMPLATE_OF_DATA_FRAMES= %(template)s ! REFERENCE_DATA_SET=xxx/XDS_ASCII.HKL ! e.g. to ensure consistent indexing DATA_RANGE= %(data_range)s SPOT_RANGE= %(spot_range)s ! BACKGROUND_RANGE=1 10 ! rather use defaults (first 5 degree of rotation) FRIEDEL'S_LAW= %(friedel)s DELPHI= %(delphi).2f ! parameters specifically for this detector and beamline: DETECTOR= %(detector)s SENSOR_THICKNESS= %(sensor_thickness).2f ! attention CCD detectors: for very high resolution (better than 1A) make sure to specify SILICON ! as about 32* what CORRECT.LP suggests (absorption of phosphor is much higher than that of silicon) NX= %(nx)s NY= %(ny)s QX= %(qx)s QY= %(qy)s ! to make CORRECT happy if frames are unavailable ROTATION_AXIS= %(rotation_axis)s %(extra_kwds)s """ % locals() # XXX Really, really BAD idea!! # Synchrotron can have R-AXIS, and In-house detecotr can have horizontal goniometer..!! if im.header["ImageType"] == "raxis": inp_str += """\ DIRECTION_OF_DETECTOR_X-AXIS= 1 0 0 DIRECTION_OF_DETECTOR_Y-AXIS= 0 -1 0 INCIDENT_BEAM_DIRECTION= 0 0 1 !FRACTION_OF_POLARIZATION= 0.98 ! uncomment if synchrotron POLARIZATION_PLANE_NORMAL= 1 0 0 """ else: if im.header["ImageType"] == "mscccd": inp_str += """\ DIRECTION_OF_DETECTOR_X-AXIS= -1 0 0 DIRECTION_OF_DETECTOR_Y-AXIS= 0 1 0 """ else: inp_str += """\ DIRECTION_OF_DETECTOR_X-AXIS= 1 0 0 DIRECTION_OF_DETECTOR_Y-AXIS= 0 1 0 """ inp_str += """\ INCIDENT_BEAM_DIRECTION= 0 0 1 FRACTION_OF_POLARIZATION= 0.98 ! better value is provided by beamline staff! POLARIZATION_PLANE_NORMAL= 0 1 0 """ if not minimum: inp_str += """\ SPACE_GROUP_NUMBER= %(sgnum)d ! 0 if unknown UNIT_CELL_CONSTANTS= %(cell)s ! put correct values if known INCLUDE_RESOLUTION_RANGE=50 0 ! after CORRECT, insert high resol limit; re-run CORRECT TRUSTED_REGION=0.00 1.4 ! partially use corners of detectors; 1.41421=full use VALUE_RANGE_FOR_TRUSTED_DETECTOR_PIXELS=6000. 30000. ! often 7000 or 8000 is ok STRONG_PIXEL=4 ! COLSPOT: only use strong reflections (default is 3) MINIMUM_NUMBER_OF_PIXELS_IN_A_SPOT=3 ! default of 6 is sometimes too high ! close spots: reduce SEPMIN and CLUSTER_RADIUS from their defaults of 6 and 3, e.g. to 4 and 2 ! for bad or low resolution data remove the "!" in the following line: REFINE(IDXREF)=CELL BEAM ORIENTATION AXIS ! DISTANCE POSITION REFINE(INTEGRATE)= DISTANCE POSITION BEAM ORIENTATION ! AXIS CELL ! REFINE(CORRECT)=CELL BEAM ORIENTATION AXIS DISTANCE POSITION ! Default is: refine everything !used by DEFPIX and CORRECT to exclude ice-reflections / ice rings - uncomment if necessary !EXCLUDE_RESOLUTION_RANGE= 3.93 3.87 !ice-ring at 3.897 Angstrom !EXCLUDE_RESOLUTION_RANGE= 3.70 3.64 !ice-ring at 3.669 Angstrom !EXCLUDE_RESOLUTION_RANGE= 3.47 3.41 !ice-ring at 3.441 Angstrom !EXCLUDE_RESOLUTION_RANGE= 2.70 2.64 !ice-ring at 2.671 Angstrom !EXCLUDE_RESOLUTION_RANGE= 2.28 2.22 !ice-ring at 2.249 Angstrom !EXCLUDE_RESOLUTION_RANGE= 2.102 2.042 !ice-ring at 2.072 Angstrom - strong !EXCLUDE_RESOLUTION_RANGE= 1.978 1.918 !ice-ring at 1.948 Angstrom - weak !EXCLUDE_RESOLUTION_RANGE= 1.948 1.888 !ice-ring at 1.918 Angstrom - strong !EXCLUDE_RESOLUTION_RANGE= 1.913 1.853 !ice-ring at 1.883 Angstrom - weak !EXCLUDE_RESOLUTION_RANGE= 1.751 1.691 !ice-ring at 1.721 Angstrom - weak """ % dict(sgnum=sgnum, cell=cell_str) if im.header["ImageType"] == "minicbf": inp_str += """\ NUMBER_OF_PROFILE_GRID_POINTS_ALONG_ALPHA/BETA= 13 ! Default is 9 - Increasing may improve data NUMBER_OF_PROFILE_GRID_POINTS_ALONG_GAMMA= 13 ! accuracy, particularly if finely-sliced on phi, ! and does not seem to have any downsides. """ if nx == 1475: if 1: #! grep -q Flat_field tmp2: #XXX FIXME inp_str += """\ ! the following specifications are for a detector _without_ proper ! flat_field correction; they cut away one additional pixel adjacent ! to each UNTRUSTED_RECTANGLE !EXCLUSION OF VERTICAL DEAD AREAS OF THE PILATUS 2M DETECTOR UNTRUSTED_RECTANGLE= 486 496 0 1680 UNTRUSTED_RECTANGLE= 980 990 0 1680 !EXCLUSION OF HORIZONTAL DEAD AREAS OF THE PILATUS 2M DETECTOR UNTRUSTED_RECTANGLE= 0 1476 194 214 UNTRUSTED_RECTANGLE= 0 1476 406 426 UNTRUSTED_RECTANGLE= 0 1476 618 638 UNTRUSTED_RECTANGLE= 0 1476 830 850 UNTRUSTED_RECTANGLE= 0 1476 1042 1062 UNTRUSTED_RECTANGLE= 0 1476 1254 1274 UNTRUSTED_RECTANGLE= 0 1476 1466 1486 """ else: inp_str += """\ !EXCLUSION OF VERTICAL DEAD AREAS OF THE PILATUS 2M DETECTOR UNTRUSTED_RECTANGLE= 487 495 0 1680 UNTRUSTED_RECTANGLE= 981 989 0 1680 !EXCLUSION OF HORIZONTAL DEAD AREAS OF THE PILATUS 2M DETECTOR UNTRUSTED_RECTANGLE= 0 1476 195 213 UNTRUSTED_RECTANGLE= 0 1476 407 425 UNTRUSTED_RECTANGLE= 0 1476 619 637 UNTRUSTED_RECTANGLE= 0 1476 831 849 UNTRUSTED_RECTANGLE= 0 1476 1043 1061 UNTRUSTED_RECTANGLE= 0 1476 1255 1273 UNTRUSTED_RECTANGLE= 0 1476 1467 1485 """ elif nx == 2463: # Pilatus 6M # FIXME: here we could test if a Flat_field correction was applied like we do for 2M inp_str += """\ UNTRUSTED_RECTANGLE= 487 495 0 2528 UNTRUSTED_RECTANGLE= 981 989 0 2528 UNTRUSTED_RECTANGLE=1475 1483 0 2528 UNTRUSTED_RECTANGLE=1969 1977 0 2528 UNTRUSTED_RECTANGLE= 0 2464 195 213 UNTRUSTED_RECTANGLE= 0 2464 407 425 UNTRUSTED_RECTANGLE= 0 2464 619 637 UNTRUSTED_RECTANGLE= 0 2464 831 849 UNTRUSTED_RECTANGLE= 0 2464 1043 1061 UNTRUSTED_RECTANGLE= 0 2464 1255 1273 UNTRUSTED_RECTANGLE= 0 2464 1467 1485 UNTRUSTED_RECTANGLE= 0 2464 1679 1697 UNTRUSTED_RECTANGLE= 0 2464 1891 1909 UNTRUSTED_RECTANGLE= 0 2464 2103 2121 UNTRUSTED_RECTANGLE= 0 2464 2315 2333 """ if is_eiger_hdf5 and nx == 3110 and ny == 3269: # Eiger 9M inp_str += """\ UNTRUSTED_RECTANGLE= 1029 1042 0 3269 UNTRUSTED_RECTANGLE= 2069 2082 0 3269 UNTRUSTED_RECTANGLE= 0 3110 513 553 UNTRUSTED_RECTANGLE= 0 3110 1064 1104 UNTRUSTED_RECTANGLE= 0 3110 1615 1655 UNTRUSTED_RECTANGLE= 0 3110 2166 2206 UNTRUSTED_RECTANGLE= 0 3110 2717 2757 """ return inp_str
if __name__ == "__main__": import sys import optparse parser = optparse.OptionParser(usage="usage: %prog [options] img_files") parser.add_option( "--file-timestamp", "-f", action="store_true", dest="file_timestamp", help="Use file system time stamp instead of detector header") opts, args = parser.parse_args(sys.argv) img_date = [] for f in args[1:]: if opts.file_timestamp: img_date.append((f, os.path.getmtime(f))) else: im = XIO.Image(f) img_date.append((f, im.header["DateSeconds"])) img_date.sort(key=lambda x: x[1]) print "DateStr TimeDiff Filename" for i in xrange(len(img_date)): print time.ctime(img_date[i][1]), print "%10d %s" % (img_date[i][1] - img_date[0][1], img_date[i][0])
def find_spots(img_file, params): """ Use XDS to locate spots. If params.xds.do_defpix is true, DEFPIX will be run. For DEFPIX, dummy XPARM.XDS is needed. Thanks to DEFPIX, we can mask beam stop shadow and remove areas outside the resolution range. If false, we need to set TRUSTED_REGION to exclude regions outside resolution range, but it is independent of beam center. Maybe we should remove spots outside the resolution range after XDS run? """ # Test if ramdisk available if os.path.isdir("/dev/shm"): work_dir = tempfile.mkdtemp( prefix="shika_x_" + os.path.splitext(os.path.basename(img_file))[0], dir="/dev/shm") else: work_dir = os.path.join( params.work_dir, "xds_" + os.path.splitext(os.path.basename(img_file))[0]) xdsinp = os.path.join(work_dir, "XDS.INP") spot_xds = os.path.join(work_dir, "SPOT.XDS") if not os.path.exists(work_dir): os.mkdir(work_dir) template_str, min_frame, max_frame = dataset.group_img_files_template( [img_file])[0] im = XIO.Image(img_file) # Remove lines if None (means to use default) params_maps = [ ("strong_pixel", "STRONG_PIXEL="), ("minimum_number_of_pixels_in_a_spot", "MINIMUM_NUMBER_OF_PIXELS_IN_A_SPOT="), ("background_pixel", "BACKGROUND_PIXEL="), ("maximum_number_of_strong_pixels", "MAXIMUM_NUMBER_OF_STRONG_PIXELS="), ("spot_maximum_centroid", "SPOT_MAXIMUM-CENTROID="), ("reflecting_range", "REFLECTING_RANGE="), ("value_range_for_trusted_detector_pixels", "VALUE_RANGE_FOR_TRUSTED_DETECTOR_PIXELS="), ] tmp = xds_inp_template.splitlines() for p, x in params_maps: if getattr(params.xds, p) is None: tmp = filter(lambda s: not s.startswith(x), tmp) inp_template = "\n".join(tmp) # Prepare XDS.INP inp_str = inp_template % dict( template=os.path.relpath(template_str, work_dir), framenum=min_frame, orgx=im.header["BeamX"] / im.header["PixelX"], orgy=im.header["BeamY"] / im.header["PixelY"], distance=im.header["Distance"], osc_range=im.header["PhiWidth"], wavelength=im.header["Wavelength"], strong_pixel=params.xds.strong_pixel, min_pixels=params.xds.minimum_number_of_pixels_in_a_spot, background_pixel=params.xds.background_pixel, max_strong_pixels=params.xds.maximum_number_of_strong_pixels, spot_maximum_centroid=params.xds.spot_maximum_centroid, reflecting_range=params.xds.reflecting_range, nx=im.header["Width"], ny=im.header["Height"], qx=im.header["PixelX"], qy=im.header["PixelY"], defpix_trusted1=params.xds.value_range_for_trusted_detector_pixels[0], defpix_trusted2=params.xds.value_range_for_trusted_detector_pixels[1]) open(xdsinp, "w").write(inp_str) if params.xds.do_defpix: xp = xparm.XPARM() xp.set_info_from_xdsinp(xdsinp) open(os.path.join(work_dir, "XPARM.XDS"), "w").write(xp.xparm_str()) modify_xdsinp(xdsinp, inp_params=[("JOB", "XYCORR INIT DEFPIX"), ("INCLUDE_RESOLUTION_RANGE", res_range_for_xds(params.distl.res.outer, params.distl.res.inner))]) call("xds", wdir=work_dir, stdout=open(os.path.join(work_dir, "xds.log"), "w")) shutil.copy(os.path.join(work_dir, "BKGPIX.cbf"), os.path.join(work_dir, "BKGINIT.cbf")) modify_xdsinp(xdsinp, inp_params=[("JOB", "COLSPOT")]) else: modify_xdsinp(xdsinp, inp_params=[ ("TRUSTED_REGION", res_range_to_trusted_region(params.distl.res.outer, params.distl.res.inner, im.header)) ]) open(os.path.join(work_dir, "xds.log"), "w").write("") # Run XDS rotate_file(spot_xds) call("xds", wdir=work_dir, stdout=open(os.path.join(work_dir, "xds.log"), "a")) # Extract results spots = [] # (x, y, d, intensity) if os.path.isfile(spot_xds): for l in open(spot_xds): x, y, z, intensity = map(lambda x: float(x), l.strip().split()) d = coord_to_resol(x, y, im.header) spots.append((x, y, d, intensity)) # Delete dir shutil.rmtree(work_dir) return spots
def generate_xds_inp(img_files, inp_dir, use_dxtbx=False, anomalous=True, reverse_phi=None, spot_range=None, minimum=False, crystal_symmetry=None, integrate_nimages=None, osc_range=None, orgx=None, orgy=None, rotation_axis=None, distance=None, wavelength=None, minpk=None, exclude_resolution_range=None, fstart=None, fend=None, extra_kwds=None, overrides=None, fix_geometry_when_overridden=False): """ Reference: http://strucbio.biologie.uni-konstanz.de/xdswiki/index.php/Generate_XDS.INP """ if not exclude_resolution_range: exclude_resolution_range = [] if not extra_kwds: extra_kwds = [] if not overrides: overrides = [] is_eiger_hdf5 = (len(img_files) == 1 and "_master.h5" in img_files[0]) if is_eiger_hdf5: template = img_files[0].replace("_master.h5", "_??????.h5") else: groups = group_img_files_template(img_files) assert len(groups) == 1 template, fstart, fend = groups[ 0] # arguments fstart, fend are overwritten here #print inp_dir, img_files[0], template tmp = [ os.path.dirname(os.path.relpath(img_files[0], inp_dir)), os.path.dirname(os.path.abspath(img_files[0])) ] imdir = min(tmp, key=lambda x: len(x)) template = os.path.join(imdir, os.path.basename(template)) #print imdir if crystal_symmetry is None: sgnum = 0 cell_str = "50 60 70 90 90 90" else: sgnum = crystal_symmetry.space_group_info().type().number() cell_str = " ".join( map(lambda x: "%.2f" % x, crystal_symmetry.unit_cell().parameters())) data_range = "%d %d" % (fstart, fend) if spot_range is None: spot_range = "%d %d" % (fstart, (fend + fstart) / 2) elif spot_range == "first": spot_range = "%d %d" % (fstart, fstart) elif spot_range == "all": spot_range = "%d %d" % (fstart, fend) elif len(spot_range) == 2: spot_range = "%d %d" % spot_range else: print "Error!" return friedel = "FALSE" if anomalous else "TRUE" is_pilatus_or_eiger = False img_files_existed = filter(lambda x: os.path.isfile(x), img_files) if not img_files_existed: raise Exception("No actual images found.") inp_str = """\ MAXIMUM_NUMBER_OF_JOBS= 1 JOB= XYCORR INIT COLSPOT IDXREF DEFPIX INTEGRATE CORRECT NAME_TEMPLATE_OF_DATA_FRAMES= %(template)s DATA_RANGE= %(data_range)s SPOT_RANGE= %(spot_range)s !BACKGROUND_RANGE=1 10 FRIEDEL'S_LAW= %(friedel)s """ % locals() if use_dxtbx: # This is the current limitation.. assert all(x is None for x in (osc_range, orgx, orgy, rotation_axis, distance, wavelength)) toxds, inplst = read_geometry_using_dxtbx(img_files_existed[0]) inp_str += "\n".join(inplst) + "\n" osc_range = toxds.oscillation_range nx, ny = toxds.detector_size is_pilatus_or_eiger = toxds.get_detector()[0].get_type( ) == "SENSOR_PAD" else: im = XIO.Image(img_files_existed[0]) if osc_range is None: osc_range = im.header["PhiWidth"] if rotation_axis is None: # automatic decision if "OscAxisVec" in im.header: rotation_axis = im.header["OscAxisVec"] print "DEBUG::rotation_axis from header:", rotation_axis else: if im.header["ImageType"] == "raxis": rotation_axis = (0, 1, 0) else: rotation_axis = (1, 0, 0) if reverse_phi is None: # automatic decision REVERSEPHI_SNs = dict( marccd="""\ 24 31 38 40 42 106 """.split(), # Known detectors for reversed-phi in SPring-8: 24: BL26B2 Mar225, 31: BL32XU MX225HE, 38: BL44XU MX225HE, 42: BL44XU MX300HE, 40: BL41XU MX225HE, 106: BL32XU MX225HS adsc="""\ 915 458 924 """.split(), # Known detectors for reversed-phi in SPring-8: 915: BL38B1 Q315; APS 19-ID: 458; BM30A: 924 minicbf="""\ PILATUS3 6M, S/N 60-0125 PILATUS3 6M, S/N 60-0132 PILATUS 2M, S/N 24-0109 """.splitlines(), # Known detectors for reversed-phi in SPring-8: BL41XU PILATUS3 6M 60-0125, APS: 19ID PILATUS3 6M 60-0132, MX2 beamline (Brazilian Synchrotron National Laboratory - LNLS) ) if im.header.get("SerialNumber") in REVERSEPHI_SNs.get( im.header["ImageType"], ()): print "DEBUG:: this is reversephi of", rotation_axis reverse_phi = True if reverse_phi: rotation_axis = map(lambda x: -1 * x, rotation_axis) rotation_axis = " ".join(map(lambda x: "%.6f" % x, rotation_axis)) nx, ny = im.header["Width"], im.header["Height"], qx, qy = im.header["PixelX"], im.header["PixelY"] if orgx is None: orgx = im.header["BeamX"] / qx if orgy is None: orgy = im.header["BeamY"] / qy if wavelength is None: wavelength = im.header["Wavelength"] if distance is None: distance = im.header["Distance"] sensor_thickness = 0 # FIXME if im.header["ImageType"] == "marccd": detector = "CCDCHESS MINIMUM_VALID_PIXEL_VALUE= 1 OVERLOAD= 65500" elif im.header["ImageType"] == "raxis": detector = "RAXIS MINIMUM_VALID_PIXEL_VALUE= 0 OVERLOAD= 2000000" distance *= -1 elif im.header["ImageType"] == "minicbf": detector = "PILATUS MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD= 1048576" sensor_thickness = sensor_thickness_from_minicbf(img_files[0]) is_pilatus_or_eiger = True elif im.header["ImageType"] == "adsc": detector = "ADSC MINIMUM_VALID_PIXEL_VALUE= 1 OVERLOAD= 65000" elif im.header["ImageType"] == "mscccd": detector = "SATURN MINIMUM_VALID_PIXEL_VALUE= 1 OVERLOAD= 262112" # XXX Should read header!! distance *= -1 elif is_eiger_hdf5: detector = "EIGER MINIMUM_VALID_PIXEL_VALUE=0 OVERLOAD= %d" % im.header[ "Overload"] sensor_thickness = im.header["SensorThickness"] is_pilatus_or_eiger = True inp_str += """\ ORGX= %(orgx).2f ORGY= %(orgy).2f DETECTOR_DISTANCE= %(distance).2f OSCILLATION_RANGE= %(osc_range).3f X-RAY_WAVELENGTH= %(wavelength).5f DETECTOR= %(detector)s SENSOR_THICKNESS= %(sensor_thickness).2f NX= %(nx)s NY= %(ny)s QX= %(qx)s QY= %(qy)s ROTATION_AXIS= %(rotation_axis)s INCIDENT_BEAM_DIRECTION= 0 0 1 FRACTION_OF_POLARIZATION= 0.98 POLARIZATION_PLANE_NORMAL= 0 1 0 """ % locals() # XXX Synchrotron can have R-AXIS, and In-house detecotr can have horizontal goniometer! if im.header["ImageType"] == "raxis": inp_str += """\ DIRECTION_OF_DETECTOR_X-AXIS= 1 0 0 DIRECTION_OF_DETECTOR_Y-AXIS= 0 -1 0 INCIDENT_BEAM_DIRECTION= 0 0 1 !FRACTION_OF_POLARIZATION= 0.98 ! uncomment if synchrotron POLARIZATION_PLANE_NORMAL= 1 0 0 """ else: if im.header["ImageType"] == "mscccd": inp_str += """\ DIRECTION_OF_DETECTOR_X-AXIS= -1 0 0 DIRECTION_OF_DETECTOR_Y-AXIS= 0 1 0 """ else: inp_str += """\ DIRECTION_OF_DETECTOR_X-AXIS= 1 0 0 DIRECTION_OF_DETECTOR_Y-AXIS= 0 1 0 """ if integrate_nimages is None: extra_kwds.append(" DELPHI= 5") else: extra_kwds.append(" DELPHI= %.4f" % osc_range * integrate_nimages) if minpk is not None: extra_kwds.append(" MINPK= %.2f" % minpk) for r1, r2 in exclude_resolution_range: if r1 < r2: r1, r2 = r2, r1 extra_kwds.append(" EXCLUDE_RESOLUTION_RANGE= %.3f %.3f" % (r1, r2)) extra_kwds = "\n".join(extra_kwds) + "\n" inp_str += extra_kwds if not minimum: inp_str += """\ SPACE_GROUP_NUMBER= %(sgnum)d UNIT_CELL_CONSTANTS= %(cell)s INCLUDE_RESOLUTION_RANGE=50 0 TRUSTED_REGION=0.00 1.4 VALUE_RANGE_FOR_TRUSTED_DETECTOR_PIXELS=6000. 30000. STRONG_PIXEL=4 MINIMUM_NUMBER_OF_PIXELS_IN_A_SPOT=3 REFINE(IDXREF)=CELL BEAM ORIENTATION AXIS ! DISTANCE POSITION REFINE(INTEGRATE)= DISTANCE POSITION BEAM ORIENTATION ! AXIS CELL !REFINE(CORRECT)=CELL BEAM ORIENTATION AXIS DISTANCE POSITION """ % dict(sgnum=sgnum, cell=cell_str) if is_pilatus_or_eiger: inp_str += """\ NUMBER_OF_PROFILE_GRID_POINTS_ALONG_ALPHA/BETA= 13 NUMBER_OF_PROFILE_GRID_POINTS_ALONG_GAMMA= 13 """ if nx == 1475 and ny == 1679: # Pilatus 2M inp_str += """\ !EXCLUSION OF VERTICAL DEAD AREAS OF THE PILATUS 2M DETECTOR UNTRUSTED_RECTANGLE= 486 496 0 1680 UNTRUSTED_RECTANGLE= 980 990 0 1680 !EXCLUSION OF HORIZONTAL DEAD AREAS OF THE PILATUS 2M DETECTOR UNTRUSTED_RECTANGLE= 0 1476 194 214 UNTRUSTED_RECTANGLE= 0 1476 406 426 UNTRUSTED_RECTANGLE= 0 1476 618 638 UNTRUSTED_RECTANGLE= 0 1476 830 850 UNTRUSTED_RECTANGLE= 0 1476 1042 1062 UNTRUSTED_RECTANGLE= 0 1476 1254 1274 UNTRUSTED_RECTANGLE= 0 1476 1466 1486 """ elif nx == 2463 and ny == 2527: # Pilatus 6M inp_str += """\ UNTRUSTED_RECTANGLE= 487 495 0 2528 UNTRUSTED_RECTANGLE= 981 989 0 2528 UNTRUSTED_RECTANGLE=1475 1483 0 2528 UNTRUSTED_RECTANGLE=1969 1977 0 2528 UNTRUSTED_RECTANGLE= 0 2464 195 213 UNTRUSTED_RECTANGLE= 0 2464 407 425 UNTRUSTED_RECTANGLE= 0 2464 619 637 UNTRUSTED_RECTANGLE= 0 2464 831 849 UNTRUSTED_RECTANGLE= 0 2464 1043 1061 UNTRUSTED_RECTANGLE= 0 2464 1255 1273 UNTRUSTED_RECTANGLE= 0 2464 1467 1485 UNTRUSTED_RECTANGLE= 0 2464 1679 1697 UNTRUSTED_RECTANGLE= 0 2464 1891 1909 UNTRUSTED_RECTANGLE= 0 2464 2103 2121 UNTRUSTED_RECTANGLE= 0 2464 2315 2333 """ elif nx == 3110 and ny == 3269: # Eiger 9M inp_str += """\ UNTRUSTED_RECTANGLE= 1029 1042 0 3269 UNTRUSTED_RECTANGLE= 2069 2082 0 3269 UNTRUSTED_RECTANGLE= 0 3110 513 553 UNTRUSTED_RECTANGLE= 0 3110 1064 1104 UNTRUSTED_RECTANGLE= 0 3110 1615 1655 UNTRUSTED_RECTANGLE= 0 3110 2166 2206 UNTRUSTED_RECTANGLE= 0 3110 2717 2757 """ if overrides: inp_str += "\n! Overriding parameters:\n" inp_str += "\n".join(overrides) + "\n" if fix_geometry_when_overridden: inp_str += " REFINE(IDXREF)= CELL ORIENTATION ! BEAM AXIS DISTANCE POSITION\n" inp_str += " REFINE(INTEGRATE)= CELL ORIENTATION ! DISTANCE POSITION BEAM AXIS\n" return inp_str
def run(cbfin): header = XIO.Image(cbfin).header make_geom(header, "pilatus.geom")