def spline_plot_cycles(cart_coords, energies): num_cycles = energies.shape[1] fig, ax = plt.subplots() colors = matplotlib.cm.Greys(np.linspace(.2, 1, num=num_cycles)) # for cycle, color in zip(energies, colors): for i, (cycle, color) in enumerate(zip(energies, colors)): ax.plot(cycle, "o-", color=color) ax.set_title("COS image energies") kwargs = { "ls": ":", "color": "darkgrey", } # Try to spline the last cycle to get an estimate for the spliend HEI try: last_cycle = energies[-1] num_images = last_cycle.size spl = splrep(np.arange(num_images), last_cycle) # Calculate interpolated values x2 = np.linspace(0, num_images, 100) y2 = splev(x2, spl) # Only consider maxima peak_inds, _ = peakdetect(y2, lookahead=2) if not peak_inds: ax.plot(x2, y2) else: peak_inds = np.array(peak_inds)[:, 0].astype(int) peak_xs = x2[peak_inds] peak_ys = y2[peak_inds] ax.plot(x2, y2, peak_xs, peak_ys, "x") for px, py in zip(peak_xs, peak_ys): ax.axhline(y=py, **kwargs) line = matplotlib.lines.Line2D([px, px], [0, py], **kwargs) ax.add_line(line) except TypeError: print("Not enough images for splining!") # Always draw a line at the minimum y=0 ax.axhline(y=0, **kwargs) ax.set_xlabel("Image") ax.set_ylabel(UNIT_DEKJMOL) return fig, ax
def plot_afir(): with open("image_results.yaml") as handle: res = yaml.load(handle.read(), Loader=yaml.loader.Loader) afir_ens = [_["energy"] for _ in res] true_ens = [_["true_energy"] for _ in res] afir_ens = np.array(afir_ens) * AU2KJPERMOL afir_ens -= afir_ens.min() true_ens = np.array(true_ens) * AU2KJPERMOL true_ens -= true_ens.min() afir_forces = np.linalg.norm([_["forces"] for _ in res], axis=1) true_forces = np.linalg.norm([_["true_forces"] for _ in res], axis=1) afir_forces = np.array(afir_forces) true_forces = np.array(true_forces) fig, (en_ax, forces_ax) = plt.subplots(nrows=2, sharex=True) style1 = "r--" style2 = "g--" style3 = "bo-" l1 = en_ax.plot(afir_ens, style1, label="AFIR") l2 = en_ax.plot(true_ens, style2, label="True") en_ax2 = en_ax.twinx() l3 = en_ax2.plot(true_ens + afir_ens, style3, label="Sum") en_ax2.tick_params(axis="y", labelcolor="blue") lines = l1 + l2 + l3 labels = [l.get_label() for l in lines] en_ax.legend(lines, labels, loc=0) en_ax.set_title("Energies") en_ax.set_ylabel("$\Delta$E kJ / mol") forces_ax.set_title("||Forces||") l1 = forces_ax.plot(afir_forces, style1, label="AFIR") l2 = forces_ax.plot(true_forces, style2, label="True") forces_ax2 = forces_ax.twinx() l3 = forces_ax2.plot(true_forces + afir_forces, style3, label="Sum") forces_ax2.tick_params(axis="y", labelcolor="blue") lines = l1 + l2 + l3 labels = [l.get_label() for l in lines] forces_ax.legend(lines, labels, loc=0) peak_inds, _ = peakdetect(true_ens, lookahead=2) print(f"Peaks: {peak_inds}") try: peak_xs, peak_ys = zip(*peak_inds) highest = np.argmax(peak_ys) en_ax.scatter(peak_xs, peak_ys, s=100, marker="X", c="k", zorder=10) en_ax.scatter(peak_xs[highest], peak_ys[highest], s=150, marker="X", c="k", zorder=10) en_ax.axvline(peak_xs[highest], c="k", ls="--") forces_ax.axvline(peak_xs[highest], c="k", ls="--") except ValueError as err: print("Peak-detection failed!") # fig.legend(loc="upper right") plt.tight_layout() plt.show()
def plot_energies(): keys = ("energy", "cart_coords") (energies, coords), num_cycles, num_images = load_results(keys) if isinstance(num_images, list): print("Please use --aneb instead of --energies") return lengths = np.array([len(e) for e in energies]) equal_lengths = lengths == lengths[-1] # Hack to support growing string calculations energies = np.array([e for e, l in zip(energies, equal_lengths) if l]) coords = np.array([c for c, l in zip(coords, equal_lengths) if l]) num_cycles, num_images = energies.shape energies -= energies.min() energies *= AU2KJPERMOL # Static plot of path with equally spaced images fig, ax = plt.subplots() colors = matplotlib.cm.Greys(np.linspace(.2, 1, num=num_cycles)) for cycle, color in zip(energies, colors): ax.plot(cycle, "o-", color=color) ax.set_title("Energies") kwargs = { "ls": ":", "color": "darkgrey", } try: last_cycle = energies[-1] spl = splrep(np.arange(num_images), last_cycle) # Calculate interpolated values x2 = np.linspace(0, num_images, 100) y2 = splev(x2, spl) # Only consider maxima peak_inds, _ = peakdetect(y2, lookahead=2) if not peak_inds: ax.plot(x2, y2) else: peak_inds = np.array(peak_inds)[:, 0].astype(int) peak_xs = x2[peak_inds] peak_ys = y2[peak_inds] ax.plot(x2, y2, peak_xs, peak_ys, "x") for px, py in zip(peak_xs, peak_ys): ax.axhline(y=py, **kwargs) line = matplotlib.lines.Line2D([px, px], [0, py], **kwargs) ax.add_line(line) except TypeError: print("Not enough images for splining!") # Always draw a line at the minimum y=0 ax.axhline(y=0, **kwargs) ax.set_xlabel("Image") ax.set_ylabel("dE / kJ mol⁻¹") fig2, ax2 = plt.subplots() last_energies = energies[-1].copy() xs = np.arange(len(last_energies)) ax2.plot(xs, last_energies, "o-") ax2.set_xlabel("Image") ax2.set_ylabel("$\Delta$E / kJ mol⁻¹") ax2.set_title(f"Cycle {len(energies)-1}") first_image_en = last_energies[0] last_image_en = last_energies[-1] max_en_ind = last_energies.argmax() max_en = last_energies[max_en_ind] print("Barrier heights using actual energies (not splined) from " f"cycle {energies.shape[0]-1}.") print(f"\tHighest energy image (HEI) at index {max_en_ind} (0-based)") first_barr = max_en - first_image_en print(f"\tBarrier between first image and HEI: {first_barr:.1f} kJ mol⁻¹") last_barr = max_en - last_image_en print(f"\tBarrier between last image and HEI: {last_barr:.1f} kJ mol⁻¹") # Also do an animation plotter = Plotter(coords, energies, "ΔE / au", interval=250, save=False) # This calls plt.show() plotter.animate()
def plot_afir(h5_fn="afir.h5", h5_group="afir"): with h5py.File(h5_fn, "r") as handle: group = handle[h5_group] cycles = group.attrs["cur_cycle"] + 1 afir_ens = group["energy"][:cycles] true_ens = group["true_energy"][:cycles] afir_forces = group["forces"][:cycles] true_forces = group["true_forces"][:cycles] afir_ens *= AU2KJPERMOL afir_ens -= afir_ens.min() true_ens *= AU2KJPERMOL true_ens -= true_ens.min() afir_forces = np.linalg.norm(afir_forces, axis=1) true_forces = np.linalg.norm(true_forces, axis=1) fig, (en_ax, forces_ax) = plt.subplots(nrows=2, sharex=True) style1 = "r--" style2 = "g--" style3 = "bo-" l1 = en_ax.plot(afir_ens, style1, label="AFIR") l2 = en_ax.plot(true_ens, style2, label="True") en_ax2 = en_ax.twinx() l3 = en_ax2.plot(true_ens + afir_ens, style3, label="Sum") en_ax2.tick_params(axis="y", labelcolor="blue") lines = l1 + l2 + l3 labels = [l.get_label() for l in lines] en_ax.legend(lines, labels, loc=0) en_ax.set_title("Energies") en_ax.set_ylabel(UNIT_DEKJMOL) forces_ax.set_title("||Forces||") l1 = forces_ax.plot(afir_forces, style1, label="AFIR") l2 = forces_ax.plot(true_forces, style2, label="True") forces_ax2 = forces_ax.twinx() l3 = forces_ax2.plot(true_forces + afir_forces, style3, label="Sum") forces_ax2.tick_params(axis="y", labelcolor="blue") lines = l1 + l2 + l3 labels = [l.get_label() for l in lines] forces_ax.legend(lines, labels, loc=0) forces_ax.set_xlabel("Cycle") peak_inds, _ = peakdetect(true_ens, lookahead=2) if peak_inds: print(f"Peaks:") print("\tCycle: Energy / kJ mol⁻¹") print() for at, energy in peak_inds: print(f"\t{at}: {energy:.2f}") try: peak_xs, peak_ys = zip(*peak_inds) highest = np.argmax(peak_ys) en_ax.scatter(peak_xs, peak_ys, s=100, marker="X", c="k", zorder=10) en_ax.scatter(peak_xs[highest], peak_ys[highest], s=150, marker="X", c="k", zorder=10) en_ax.axvline(peak_xs[highest], c="k", ls="--") forces_ax.axvline(peak_xs[highest], c="k", ls="--") except ValueError as err: print("Peak-detection failed!") # fig.legend(loc="upper right") plt.tight_layout() plt.show()