def merge(hklout="fast_dp.mtz", aimless_log="aimless.log"): """Merge the reflections from XDS_ASCII.HKL with Aimless to get statistics - this will use pointless for the reflection file format mashing.""" run_job("pointless", ["-c", "xdsin", "XDS_ASCII.HKL", "hklout", "xds_sorted.mtz"]) log = run_job( "aimless", ["hklin", "xds_sorted.mtz", "hklout", hklout, "xmlout", "aimless.xml"], [ "bins 20", "run 1 all", "scales constant", "anomalous on", "cycles 0", "output unmerged", "sdcorrection norefine full 1 0 0", ], ) with open(aimless_log, "w") as fout: for record in log: fout.write(record) # check for errors for record in log: if "!!!! No data !!!!" in record: raise RuntimeError("aimless complains no data") return parse_aimless_log(log)
def scale(unit_cell, xds_inp, space_group_number, resolution_high=0.0): """Perform the scaling with the spacegroup and unit cell calculated from pointless and correct. N.B. this scaling is done by CORRECT.""" assert unit_cell assert xds_inp assert space_group_number with open("CORRECT.INP", "w") as fout: for k in sorted(xds_inp): if "SEGMENT" in k: continue v = xds_inp[k] if isinstance(v, list): for _v in v: fout.write("%s=%s\n" % (k, _v)) else: fout.write("%s=%s\n" % (k, v)) fout.write("SPACE_GROUP_NUMBER=%d\n" % space_group_number) fout.write("UNIT_CELL_CONSTANTS=%f %f %f %f %f %f\n" % tuple(unit_cell)) fout.write("JOB=CORRECT\n") fout.write("REFINE(CORRECT)=CELL AXIS ORIENTATION POSITION BEAM\n") fout.write("INCLUDE_RESOLUTION_RANGE= 100 %f\n" % resolution_high) fout.write("%s\n" % segment_text(xds_inp)) shutil.copyfile("CORRECT.INP", "XDS.INP") run_job("xds_par") # once again should check on the general happiness of everything... for step in ["CORRECT"]: lastrecord = open("%s.LP" % step).readlines()[-1] if "!!! ERROR !!!" in lastrecord: raise RuntimeError( "error in %s: %s" % (step, lastrecord.replace("!!! ERROR !!!", "").strip())) # and get the postrefined cell constants from GXPARM.XDS - but continue # to work for the old format too... with open("GXPARM.XDS", "r") as fh: gxparm = fh.readlines() if gxparm and "XPARM.XDS" in gxparm[0]: # new format space_group = spacegroup_number_to_name(int(gxparm[3].split()[0])) unit_cell = tuple(map(float, gxparm[3].split()[1:])) else: # old format: space_group = spacegroup_number_to_name(int(gxparm[7].split()[0])) unit_cell = tuple(map(float, gxparm[7].split()[1:])) # FIXME also get the postrefined mosaic spread out... # and the total number of good reflections nref = 0 for record in open("CORRECT.LP", "r"): if "NUMBER OF ACCEPTED OBSERVATIONS" in record: nref = int(record.split()[-1]) refined_beam = read_xparm_get_refined_beam("GXPARM.XDS") # hack in xdsstat (but don't cry if it fails) xdsstat_output = run_job("xdsstat", [], ["XDS_ASCII.HKL"]) with open("xdsstat.log", "w") as fh: fh.write("".join(xdsstat_output)) return unit_cell, space_group, nref, refined_beam
def autoindex(xds_inp, input_cell=None): """Perform the autoindexing, using metatdata, get a list of possible lattices and record / return the triclinic cell constants (get these from XPARM.XDS).""" assert xds_inp xds_inp = add_spot_range(xds_inp) with open("AUTOINDEX.INP", "w") as fout: for k in sorted(xds_inp): if "SEGMENT" in k: continue v = xds_inp[k] if isinstance(v, list): for _v in v: fout.write("%s=%s\n" % (k, _v)) else: fout.write("%s=%s\n" % (k, v)) fout.write("%s\n" % segment_text(xds_inp)) if input_cell: fout.write("SPACE_GROUP_NUMBER=1\n") fout.write("UNIT_CELL_CONSTANTS=%f %f %f %f %f %f\n" % tuple(input_cell)) fout.write("JOB=XYCORR INIT COLSPOT IDXREF\n") fout.write("REFINE(IDXREF)=CELL AXIS ORIENTATION POSITION BEAM\n") fout.write("MAXIMUM_ERROR_OF_SPOT_POSITION= 2.0\n") fout.write("MINIMUM_FRACTION_OF_INDEXED_SPOTS= 0.5\n") shutil.copyfile("AUTOINDEX.INP", "XDS.INP") log = run_job("xds_par") with open("autoindex.log", "w") as fout: fout.write("".join(log)) # sequentially check for errors... XYCORR INIT COLSPOT IDXREF for step in ["XYCORR", "INIT", "COLSPOT", "IDXREF"]: lastrecord = open("%s.LP" % step).readlines()[-1] if "!!! ERROR !!!" in lastrecord: raise RuntimeError( "error in %s: %s" % (step, lastrecord.replace("!!! ERROR !!!", "").strip())) results = read_xds_idxref_lp("IDXREF.LP") # FIXME if input cell was given, verify that this is an allowed # permutation. If it was not, raise a RuntimeError. This remains to be # fixed write("All autoindexing results:") write("%3s %6s %6s %6s %6s %6s %6s" % ("Lattice", "a", "b", "c", "alpha", "beta", "gamma")) for r in sorted((r for r in results if isinstance(r, int)), reverse=True): cell = results[r][1] write("%7s %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f" % ( spacegroup_to_lattice(r), cell[0], cell[1], cell[2], cell[3], cell[4], cell[5], )) # should probably print this for debugging try: return results[1][1] except Exception: raise RuntimeError("getting P1 cell for autoindex")
def integrate(xds_inp, p1_unit_cell, resolution_low, n_jobs, n_processors): """Peform the integration with a triclinic basis.""" assert xds_inp assert p1_unit_cell with open("INTEGRATE.INP", "w") as fout: for k in sorted(xds_inp): if "SEGMENT" in k: continue v = xds_inp[k] if isinstance(v, list): for _v in v: fout.write("%s=%s\n" % (k, _v)) else: fout.write("%s=%s\n" % (k, v)) fout.write("REFINE(INTEGRATE)= POSITION BEAM ORIENTATION CELL\n") fout.write("JOB=DEFPIX INTEGRATE\n") fout.write("%s\n" % segment_text(xds_inp)) if n_processors: fout.write("MAXIMUM_NUMBER_OF_PROCESSORS=%d\n" % n_processors) if n_jobs: fout.write("MAXIMUM_NUMBER_OF_JOBS=%d\n" % n_jobs) fout.write("INCLUDE_RESOLUTION_RANGE= %f 0.0\n" % resolution_low) shutil.copyfile("INTEGRATE.INP", "XDS.INP") run_job("xds_par") # FIXME need to check that all was hunky-dory in here! for step in ["DEFPIX", "INTEGRATE"]: if not os.path.exists("%s.LP" % step): continue lastrecord = open("%s.LP" % step).readlines()[-1] if "!!! ERROR !!!" in lastrecord: raise RuntimeError("error in %s: %s" % (step, lastrecord.replace("!!! ERROR !!!", "").strip().lower())) if not os.path.exists("INTEGRATE.LP"): step = "INTEGRATE" for record in open("LP_01.tmp").readlines(): if "!!! ERROR !!! AUTOMATIC DETERMINATION OF SPOT SIZE " in record: raise RuntimeError("error in %s: %s" % (step, record.replace("!!! ERROR !!!", "").strip().lower())) elif "!!! ERROR !!! CANNOT OPEN OR READ FILE LP_01.tmp" in record: raise RuntimeError("integration error: cluster error") # check for some specific errors for step in ["INTEGRATE"]: for record in open("%s.LP" % step).readlines(): if "!!! ERROR !!! AUTOMATIC DETERMINATION OF SPOT SIZE " in record: raise RuntimeError("error in %s: %s" % (step, record.replace("!!! ERROR !!!", "").strip().lower())) elif "!!! ERROR !!! CANNOT OPEN OR READ FILE LP_01.tmp" in record: raise RuntimeError("integration error: cluster error") # if all was ok, look in the working directory for files named # forkintegrate_job.o341858 &c. and remove them. - N.B. this is site # specific! for f in os.listdir(os.getcwd()): if "forkintegrate_job." in f[:18]: try: os.remove(f) except Exception: pass # get the mosaic spread ranges mosaics = [] for record in open("INTEGRATE.LP"): if "CRYSTAL MOSAICITY (DEGREES)" in record: mosaics.append(float(record.split()[-1])) mosaic = sum(mosaics) / len(mosaics) return min(mosaics), mosaic, max(mosaics)