def test_plotdata(self): # regression test, see if the data outputed is the same ref_values = open("data/qaf.PlotData.json").read().strip() qfep_outs = ["data/qfep.out.1", "data/qfep.out.2"] qafs = QAnalyseFeps(qfep_outs, lra_lambdas=(1.0, 0.0)) jsonenc = plotdata.PlotDataJSONEncoder(indent=2) assert jsonenc.encode(qafs.plotdata) == ref_values
def test_plotdata(self): # regression test, see if the data outputed is the same ref_values = open("data/qad.PlotData.json").read().strip() qdyn_outs = ["data/qdyn5.log", "data/qdyn6.log"] qads = QAnalyseDyns(qdyn_outs) jsonenc = plotdata.PlotDataJSONEncoder(indent=2) pd = jsonenc.encode(qads.get_plotdata(stride=10)) # open("data/qad.tmp.json", "w").write(pd) assert pd == ref_values
def test_plotdata(self): # regression test, see if the data outputed is the same ref_data = open("data/qad.PlotData.json").read().strip() qdyn_outs = ["data/qdyn5.log", "data/qdyn6.log"] qads = QAnalyseDyns(qdyn_outs) jsonenc = plotdata.PlotDataJSONEncoder(indent=2, separators=(',', ': ')) outstr = round_json(jsonenc.encode(qads.get_plotdata(stride=10))) #open("data/qad.tmp.json", "w").write(outstr) assert outstr == ref_data
def test_plotdata(self): # regression test, see if the data outputed is the same ref_data = open("data/qaf.PlotData.json").read().strip() qfep_outs = ["data/qfep.out.1", "data/qfep.out.2"] qafs = QAnalyseFeps(qfep_outs, lra_lambdas=(1.0, 0.0)) jsonenc = plotdata.PlotDataJSONEncoder(indent=2, separators=(',', ': ')) outstr = round_json(jsonenc.encode(qafs.plotdata)) #open("data/qaf.tmp.json", "w").write(outstr) assert outstr == ref_data
e_dc = qads.get_energies(k, percent_skip=args.skip, stride=args.stride) e_cs, e_cts = e_dc.get_columns(), e_dc.get_column_titles() if e_cs: for i, e_ct in enumerate(e_cts[1:]): plots[key].add_subplot(e_ct, e_cs[0], e_cs[i + 1]) # 0==Time for k in qads.qen_section_keys: for evb_state in range(1, qads.n_evb_states + 1): key = "EQ{}_{}".format(evb_state, k) plots[key] = plotdata.PlotData("Q Energy: {} (state {})" "".format(k, evb_state), xlabel=time_label, ylabel="Energy [kcal/mol]") qe_dc = qads.get_q_energies(k, evb_state, percent_skip=args.skip, stride=args.stride) qe_cs, qe_cts = qe_dc.get_columns(), qe_dc.get_column_titles() if qe_cs: for i, qe_ct in enumerate(qe_cts[1:]): plots[key].add_subplot(qe_ct, qe_cs[0], qe_cs[i + 1]) # 0==Time jsonenc = plotdata.PlotDataJSONEncoder(indent=2) backup = backup_file(args.plots_out) if backup: print "Backed up '{}' to '{}'".format(args.plots_out, backup) open(args.plots_out, 'w').write(jsonenc.encode(plots)) print "\nWrote '{}'. Use q_plot.py to visualize the plots.".format( args.plots_out)
def gc(args): if not os.path.lexists(args.pdb): print "This file went missing: {}".format(args.pdb) sys.exit(1) if args.qmaskfile: try: qmask = open(args.qmaskfile, "r").read().split() if not qmask: raise IOError except IOError: print "Can't read '{}' or file empty".format(args.qmaskfile) sys.exit(1) else: qmask = None lambdas = [] for lamb in args.lra_l: try: lamb = float(lamb) if lamb < 0 or lamb > 1: raise ValueError except ValueError: print "FATAL! Lambda values make no sense. 0 <= lambda <= 1 please." sys.exit(1) lambdas.append((lamb, 1 - lamb)) calcdirs = args.dirs if not calcdirs: lsdir = os.listdir(os.getcwd()) calcdirs = [f for f in lsdir if os.path.isdir(f)] if not calcdirs: calcdirs = [ os.getcwd(), ] print "No subdirectories. Calculating in current directory only.\n" else: print "Will use these directories for calculating GCs (use --dirs to "\ "change this): {}\n".format(", ".join(calcdirs)) qgc = QGroupContrib(args.qcalc_exec, calcdirs, args.pdb, QScfg.get("files", "en_list_fn"), lambdas[0], lambdas[1], args.resid_first, args.resid_last, args.scale_ionized, args.nthreads, qmask) try: qgc.calcall() except QGroupContribError as error_msg: print "\nMassive fail:\n{}\n".format(error_msg) sys.exit(1) except KeyboardInterrupt: qgc.kill_event.set() raise # writeout QCalc inputs and outputs if args.writeout: for calcdir, (qcinps, qcouts) in qgc._qcalc_io.iteritems(): for i, qci in enumerate(qcinps): fn = os.path.join(calcdir, "q_calc.gc.{}.inp".format(i + 1)) try: open(fn, 'w').write(qci) except OSError as err: print "Error when writing to {}: {}".format(fn, err) else: print "Wrote {}".format(fn) for i, qco in enumerate(qcouts): fn = os.path.join(calcdir, "q_calc.gc.{}.out".format(i + 1)) try: open(fn, 'w').write(qco) except OSError as err: print "Error when writing to {}: {}".format(fn, err) else: print "Wrote {}".format(fn) # write out details and top 10 GCs to stdout and outfile if not qgc.gcs: top_gcs = "None, all directories failed..." top_gcs_reorg = "None, all directories failed..." else: top_rows = sorted(qgc.gcs_stats.get_rows(), key=lambda x: -abs(x[13]))[:10] out_l = ["{:<10} {:>10} {:>10}".format("# Residue", "Mean", "Stdev")] for row in top_rows: rid, rn, el, elstd = row[0], row[1], row[13], row[14] tmp = "{}_{}".format(rn.capitalize(), rid) tmp2 = "{:<10} {:10.2f} {:10.2f}".format(tmp, el, elstd) out_l.append(tmp2) top_gcs = "\n".join(out_l) top_rows = sorted(qgc.gcs_stats.get_rows(), key=lambda x: -abs(x[17]))[:10] out_l = ["{:<10} {:>10} {:>10}".format("# Residue", "Mean", "Stdev")] for row in top_rows: rid, rn, el, elstd = row[0], row[1], row[17], row[18] tmp = "{}_{}".format(rn.capitalize(), rid) tmp2 = "{:<10} {:10.2f} {:10.2f}".format(tmp, el, elstd) out_l.append(tmp2) top_gcs_reorg = "\n".join(out_l) outstr = """ {gc_details} Top LRA (el) contributions: {top_gcs} Top REORG (el) contributions: {top_gcs_reorg} """.format(gc_details=qgc.details, top_gcs=top_gcs, top_gcs_reorg=top_gcs_reorg) print outstr fn_out = args.output_fn backup = backup_file(fn_out) if backup: print "# Backed up '{}' to '{}'".format(fn_out, backup) open(fn_out, "w").write(outstr) print "Wrote '{}'...".format(fn_out) # convert plots to json and write them out fn_out = args.plots_out plots = qgc.plotdata jsonenc = plotdata.PlotDataJSONEncoder(indent=2) backup = backup_file(fn_out) if backup: print "# Backed up '{}' to '{}'".format(fn_out, backup) open(fn_out, 'w').write(jsonenc.encode(plots)) print "Wrote '{}'... (q_plot.py is your "\ "friend)".format(fn_out) # writeout the pdbgc if requested if args.pdbgc_out: backup = backup_file(args.pdbgc_out) if backup: print "# Backed up '{}' to '{}'".format(args.pdbgc_out, backup) open(args.pdbgc_out, 'w').write(qgc.get_pdbgc()) print "Wrote '{}'... (use Pymol/Chimera/VMD and color by occupancy "\ "(LRA) or B-factor (reorg))".format(args.pdbgc_out)
def main(): logger = init_logger('Qpyl') parser = argparse.ArgumentParser(description=""" Tool for analysing QFep outputs - extracting FEP results, activation and reaction free energies, calculating LRA contributions, calculating statistics over all outputs, and exporting all the data into JSON format. Should be used after every mapping. """, add_help=False) reqarg = parser.add_argument_group("Required") reqarg.add_argument("fepdirs", nargs="+", help="Directories to scan for qfep output.") optarg = parser.add_argument_group("Optional") def_lra_l = QScfg.get("analysis", "lambdas_state1").split(",") optarg.add_argument("--lra_l", dest="lra_l", nargs=2, metavar=("l1", "l2"), default=def_lra_l, help="Specify lambdas (state 1) at which LRA and " "REORG are calculated. Default is '{}'." "".format(str(def_lra_l))) optarg.add_argument("--qfep_out", dest="qfep_out", help="Qfep output filename (default='{}')" "".format(QScfg.get("files", "qfep_out")), default=QScfg.get("files", "qfep_out")) optarg.add_argument("--out", dest="output_fn", help="Output filename (default='{}')" "".format(QScfg.get("files", "analysefeps_log")), default=QScfg.get("files", "analysefeps_log")) optarg.add_argument("--plots_out", dest="plots_out", help="Output filename for plot data (default='{}')" "".format(QScfg.get("files", "analysefeps_plots")), default=QScfg.get("files", "analysefeps_plots")) optarg.add_argument("--subcalcs", dest="subcalcs", default=False, help="Write out plot data for sub-calculations " "(QCP, QCP_mass, Exclusions). By default " "this data is not written out.", action="store_true") optarg.add_argument("--subcalc_dir", dest="subcalc_dir", help="Output directory for sub-calculation plot data " "Default={}".format(QScfg.get("files", \ "analysefeps_subcalc_dir")), default=QScfg.get("files", "analysefeps_subcalc_dir")) optarg.add_argument("-v", "--version", action="version", version=get_version_full()) optarg.add_argument("-h", "--help", action="help", help="show this help " " message and exit") if len(sys.argv) == 1: parser.print_help() sys.exit(1) args = parser.parse_args() lra_l = [] for lamb in args.lra_l: try: lamb = float(lamb) if lamb < 0 or lamb > 1: raise ValueError except ValueError: print("FATAL! LRA lambdas make no sense. 0<lambda<1 please.") sys.exit(1) lra_l.append(lamb) if args.subcalcs and os.path.lexists(args.subcalc_dir): print("Directory '{}' exists. Please (re)move it or "\ "use --subcalc_dir.".format(args.subcalc_dir)) sys.exit(1) # analyse the outputs qos = [os.path.join(md, args.qfep_out) for md in sorted(args.fepdirs)] qaf = QAnalyseFeps(qos, lra_lambdas=lra_l) stats, fails = [], [] # get the statistics stats.append(qaf.stats_str) for sub_calc_key, sub_calc in sorted(six.iteritems(qaf.sub_calcs)): stats.append(sub_calc.stats_str) # get those that completely failed if qaf.failed: fails.append("Failed to parse:") for failed_path, failed_msg in sorted(six.iteritems(qaf.failed)): relp = os.path.relpath(failed_path) fails.append("-> {}: {}".format(relp, failed_msg)) # get those that didn't produce dG*/dG0 if qaf.failed_dg: fails.append("Failed to produce dGa/dG0:") for failed_path, failed_msg in sorted(six.iteritems(qaf.failed_dg)): relp = os.path.relpath(failed_path) fails.append("-> {}: {}".format(relp, failed_msg)) stats = "\n".join(stats) fails = "\n".join(fails) or None summary = """ ----------------------------------- SUMMARY ----------------------------------- # Analysed with: QTools/q_analysefeps.py ({version}) # Work dir: {cwd} # Date: {date} # CMDline: {cmdline} ----- Statistics ----- {stats} ------- Fails -------- {fails} ------------------------------------------------------------------------------- """.format(version=__version__, date=time.ctime(), cwd=os.getcwd(), stats=stats, fails=fails, cmdline=" ".join(sys.argv)) print(summary) if not qaf.qfos: print("\nFATAL! None of the outputs could be parsed!") print("Are you running an ancient Q version? Then don't...") print("If not, report a bug.") sys.exit(1) # save some useful data output_string = """ ------------------------------- Free energies --------------------------------- {} {} """.format(qaf.dg_all, summary) fn_out = args.output_fn backup = backup_file(fn_out) open(fn_out, "w").write(output_string) if backup: print("Wrote '{}'... # Backed up to '{}'".format(fn_out, backup)) else: print("Wrote '{}'...".format(fn_out)) # convert plots to json and write them out fn_out = args.plots_out plots = qaf.plotdata jsonenc = plotdata.PlotDataJSONEncoder(indent=2, separators=(",", ": ")) backup = backup_file(fn_out) open(fn_out, 'w').write(jsonenc.encode(plots)) if backup: print("Wrote '{}'... (q_plot.py is your friend) "\ "# Backed up to '{}'".format(fn_out, backup)) else: print("Wrote '{}'... (q_plot.py is your friend)".format(fn_out)) # if there are sub-calculations in the outputs if qaf.sub_calcs: if not args.subcalcs: print("\nNote: These sub-calculations were found: {}. "\ "Use --subcalcs to write out the plot data."\ "".format(", ".join(qaf.sub_calcs))) sys.exit(1) else: os.mkdir(args.subcalc_dir) for subcalc_key, subcalc in six.iteritems(qaf.sub_calcs): fn_out = os.path.join(args.subcalc_dir, "qaf.{}.json".format(subcalc_key)) open(fn_out, 'w').write(jsonenc.encode(subcalc.plotdata)) print("Wrote '{}'... (q_plot.py is your "\ "friend)".format(fn_out))
if len(sys.argv) == 1: parser.print_help() sys.exit(1) args = parser.parse_args() for qdynout in args.outputs: if not os.path.lexists(qdynout): print("FATAL! File '{}' doesn't exist".format(qdynout)) sys.exit(1) try: qads = QAnalyseDyns(args.outputs, time_unit=args.timeunit, step_size=args.stepsize) except QAnalyseDynsError as e: print("Error: {}".format(e)) sys.exit(1) print(qads.get_temp_stats()) plots = qads.get_plotdata(stride=args.stride) jsonenc = plotdata.PlotDataJSONEncoder(indent=2, separators=(",", ": ")) backup = backup_file(args.plots_out) if backup: print("Backed up '{}' to '{}'".format(args.plots_out, backup)) open(args.plots_out, 'w').write(jsonenc.encode(plots)) print("\nWrote '{}'. Use q_plot.py to visualize the plots.".format( args.plots_out))