Beispiel #1
0
def init_event_server():
    utils.setup_logger()
    utils.load_all()
    utils.init_webhook_pool()

    port = utils.get_config("port")
    if port is None:
        sys.stderr.write("Unable to get Port details from Config\n")
        sys.exit(1)

    # Creating the Eventing Server, UDP Server for IPv4 packets
    try:
        serverv4 = UDPServerv4((SERVER_ADDRESSv4, port),
                               GlusterEventsRequestHandler)
    except socket.error as e:
        sys.stderr.write("Failed to start Eventsd for IPv4: {0}\n".format(e))
        sys.exit(1)
    # Creating the Eventing Server, UDP Server for IPv6 packets
    try:
        serverv6 = UDPServerv6((SERVER_ADDRESSv6, port),
                               GlusterEventsRequestHandler)
    except socket.error as e:
        sys.stderr.write("Failed to start Eventsd for IPv6: {0}\n".format(e))
        sys.exit(1)
    server_thread1 = threading.Thread(target=UDP_server_thread,
                                      args=(serverv4, ))
    server_thread2 = threading.Thread(target=UDP_server_thread,
                                      args=(serverv6, ))
    server_thread1.start()
    server_thread2.start()
def gather_fit_data(fit_count, maxfev):
    fn_format = "fits.fit_count={fit_count}_maxfev={maxfev}.txt"
    try:
        return utils.load_table(fn_format.format(**locals()))
    except OSError:
        pass

    d = utils.filter_preferred_ml(utils.load_all())
    d = d[~d["method"].isin(["imsrg[f]+eom[n]"])]
    results = []
    with multiprocessing.Pool(4) as p:
        results = p.map(
            functools.partial(gather_fit_data_inner,
                              fit_count=fit_count,
                              maxfev=maxfev),
            tuple(
                d.groupby(
                    ["label", "interaction", "num_filled", "freq", "method"])))
    d = pd.DataFrame.from_records(itertools.chain(*results))
    print("{} fits failed, out of {}".format(
        (d["fit_method"] == "fixedab").sum(), len(d)))
    # fit_count=5:
    #  maxfev=default: 198 fits failed, out of 2247
    #  maxfev=10k: 40 fits failed, out of 2248
    #  maxfev=100k: 0 fits failed

    cols = """
    interaction
    label
    freq
    num_filled
    method
    best_chisq
    best_coefficient
    best_coefficient_err
    best_constant
    best_constant_err
    best_fixedab_constant_err
    best_exponent
    best_exponent_err
    best_fit_method
    best_fit_stop
    chisq
    coefficient
    coefficient_err
    constant
    constant_err
    fixedab_constant_err
    exponent
    exponent_err
    fit_method
    fit_stop
    rel_discrep
    rel_discrep_err
    rel_dist
    rel_dist_err
    """.split()
    assert len(d.columns) == len(cols)
    utils.save_table(fn_format.format(**locals()), d[cols])
    return d
def plot(label, num_filled, freq,
         num_shells_range, interaction="normal"):
    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    d = d[(d["method"] != "imsrg[f]+eom[n]") &
          (d["method"] != "magnus_quads+eom") &
          (d["interaction"] == interaction) &
          (d["label"] == label) &
          (d["num_filled"] == num_filled) &
          (d["num_shells"] >= num_shells_range[0]) &
          (d["num_shells"] <= num_shells_range[1]) &
          (d["freq"] == 1.0)]
    num_particles = num_filled * (num_filled + 1)
    energy_type = {"ground": "ground state",
                   "add": "addition",
                   "rm": "removal"}[label]
    fig, ax = plt.subplots()
    fig.set_size_inches((4, 3))
    for method, case in d.groupby("method"):
        case = case.sort_values("num_shells")
        xs = case["num_shells"].astype(int)
        ys = case["energy"]
        ax.plot(xs, ys, "-x", label=utils.METHOD_LABEL[method],
                color=utils.METHOD_COLOR[method])
        ax.get_xaxis().set_major_locator(
            matplotlib.ticker.MaxNLocator(integer=True))
    ax.set_xlabel("K (number of shells)")
    ax.set_ylabel("E (energy)")
    ax.legend()
    fig.tight_layout()
    utils.savefig(fig,
                  "by-num-shells-{num_particles}-{num_filled}-"
                  "{label}-{ml}-{interaction}"
                  .format(**locals()))
def plot(label, num_filled, freq,
         num_shells_range, interaction="normal"):
    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    d = d[(d["method"] != "imsrg[f]+eom[n]") &
          (d["method"] != "magnus_quads+eom") &
          (d["interaction"] == interaction) &
          (d["label"] == label) &
          (d["num_filled"] == num_filled) &
          (d["num_shells"] >= num_shells_range[0]) &
          (d["num_shells"] <= num_shells_range[1]) &
          (d["freq"] == 1.0)]
    num_particles = num_filled * (num_filled + 1)
    energy_type = {"ground": "ground state",
                   "add": "addition",
                   "rm": "removal"}[label]
    fig, ax = plt.subplots()
    fig.set_size_inches((4, 3))
    for method, case in d.groupby("method"):
        case = case.sort_values("num_shells")
        xs = case["num_shells"].astype(int)
        ys = case["energy"]
        ax.plot(xs, ys, "-x", label=utils.METHOD_LABEL[method],
                color=utils.METHOD_COLOR[method])
        ax.get_xaxis().set_major_locator(
            matplotlib.ticker.MaxNLocator(integer=True))
def gather_fit_data(fit_count, maxfev):
    fn_format = "fits.fit_count={fit_count}_maxfev={maxfev}.txt"
    try:
        return utils.load_table(fn_format.format(**locals()))
    except OSError:
        pass

    d = utils.filter_preferred_ml(utils.load_all())
    d = d[~d["method"].isin(["imsrg[f]+eom[n]"])]
    results = []
    with multiprocessing.Pool(4) as p:
        results = p.map(
            functools.partial(gather_fit_data_inner,
                              fit_count=fit_count,
                              maxfev=maxfev),
            tuple(d.groupby(["label", "interaction", "num_filled",
                             "freq", "method"])))
    d = pd.DataFrame.from_records(itertools.chain(*results))
    print("{} fits failed, out of {}"
          .format((d["fit_method"] == "fixedab").sum(), len(d)))
    # fit_count=5:
    #  maxfev=default: 198 fits failed, out of 2247
    #  maxfev=10k: 40 fits failed, out of 2248
    #  maxfev=100k: 0 fits failed

    cols = """
    interaction
    label
    freq
    num_filled
    method
    best_chisq
    best_coefficient
    best_coefficient_err
    best_constant
    best_constant_err
    best_fixedab_constant_err
    best_exponent
    best_exponent_err
    best_fit_method
    best_fit_stop
    chisq
    coefficient
    coefficient_err
    constant
    constant_err
    fixedab_constant_err
    exponent
    exponent_err
    fit_method
    fit_stop
    rel_discrep
    rel_discrep_err
    rel_dist
    rel_dist_err
    """.split()
    assert len(d.columns) == len(cols)
    utils.save_table(fn_format.format(**locals()), d[cols])
    return d
Beispiel #6
0
def init_event_server():
    utils.setup_logger()

    # Delete Socket file if Exists
    try:
        os.unlink(SERVER_ADDRESS)
    except OSError:
        if os.path.exists(SERVER_ADDRESS):
            print ("Failed to cleanup socket file {0}".format(SERVER_ADDRESS),
                   file=sys.stderr)
            sys.exit(1)

    utils.load_all()

    # Start the Eventing Server, UNIX DOMAIN SOCKET Server
    GlusterEventsServer()
    asyncore.loop()
Beispiel #7
0
def init_event_server():
    utils.setup_logger()
    utils.load_all()

    port = utils.get_config("port")
    if port is None:
        sys.stderr.write("Unable to get Port details from Config\n")
        sys.exit(1)

    # Start the Eventing Server, UDP Server
    try:
        server = SocketServer.ThreadingUDPServer((SERVER_ADDRESS, port),
                                                 GlusterEventsRequestHandler)
    except socket.error as e:
        sys.stderr.write("Failed to start Eventsd: {0}\n".format(e))
        sys.exit(1)
    server.serve_forever()
Beispiel #8
0
def init_event_server():
    utils.setup_logger()

    # Delete Socket file if Exists
    try:
        os.unlink(SERVER_ADDRESS)
    except OSError:
        if os.path.exists(SERVER_ADDRESS):
            print("Failed to cleanup socket file {0}".format(SERVER_ADDRESS),
                  file=sys.stderr)
            sys.exit(1)

    utils.load_all()

    # Start the Eventing Server, UNIX DOMAIN SOCKET Server
    GlusterEventsServer()
    asyncore.loop()
def plot(label, num_filled, freq, num_shells_range):
    method_blacklist = [
        "imsrg[f]+eom[n]",
        "magnus_quads+eom",
        "fci",
        "hf",
    ]
    if label != "ground":
        method_blacklist.append("imsrg")

    fit_data = fits.load_fit_data(label)

    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    d = d[~d["method"].isin(method_blacklist) & (d["interaction"] == "normal")
          & (d["label"] == label) & (d["num_filled"] == num_filled) &
          (d["num_shells"] >= num_shells_range[0]) &
          (d["num_shells"] <= num_shells_range[1]) & (d["freq"] == freq)]
    num_particles = num_filled * (num_filled + 1)
    energy_type = {
        "ground": "ground state",
        "add": "addition",
        "rm": "removal"
    }[label]
    fig, ax = plt.subplots(1, 2)
    fig.set_size_inches((6.5, 2.3))
    base_markersize = 5
    xc = np.linspace(num_shells_range[0] - 0.5, num_shells_range[1] + 0.5, 200)
    for method, case in d.groupby("method"):
        case = case.sort_values("num_shells")
        xs = case["num_shells"].astype(int)
        ys = case["energy"]
        marker = utils.METHOD_MARKER[method]
        style = {
            "marker":
            marker,
            "markerfacecolor":
            "none",
            "markersize":
            (utils.MARKERSIZE_CORRECTION.get(marker, 1.0) * base_markersize),
            "color":
            utils.METHOD_COLOR[method],
            "label":
            utils.METHOD_LABEL[method],
        }
        xms = 0.5 * (xs[1:] + xs[:-1])
        yps = abs(ys.diff() / xs.diff())
        ax[0].plot(xms, yps, linestyle="none", **style)
        ax[1].plot(xs, ys, linestyle="none", **style)
        p = fits.get_fit_params(fit_data, np.max(xs), num_particles, freq,
                                method)
        ax[0].plot(
            xc,
            (abs(p["coefficient"] * p["exponent"]) * xc**(p["exponent"] - 1)),
            **utils.merge_dicts(style, {"marker": ""}))
        ax[1].plot(xc, p["coefficient"] * xc**p["exponent"] + p["constant"],
                   **utils.merge_dicts(style, {"marker": ""}))
Beispiel #10
0
def init_event_server():
    utils.setup_logger()
    utils.load_all()

    port = utils.get_config("port")
    if port is None:
        sys.stderr.write("Unable to get Port details from Config\n")
        sys.exit(1)

    # Start the Eventing Server, UDP Server
    try:
        server = SocketServer.ThreadingUDPServer(
            (SERVER_ADDRESS, port),
            GlusterEventsRequestHandler)
    except socket.error as e:
        sys.stderr.write("Failed to start Eventsd: {0}\n".format(e))
        sys.exit(1)
    server.serve_forever()
Beispiel #11
0
def save_fci_table(path,
                   cases=[(2, [(0.1, 5), (0.28, 5), (1.0, 5), (0.1, 10),
                               (0.28, 10), (1.0, 10)]),
                          (6, [(0.1, 8), (0.28, 8), (1.0, 8)])]):
    d = utils.load_all()
    del d["ml"]
    d = d[d["interaction"] == "normal"]
    del d["interaction"]
    d = d[d["label"] == "ground"]
    del d["label"]
    del d["num_filled"]
    d = d.set_index(["num_shells", "num_particles", "freq", "method"])

    methods = ["imsrg", "ccsd", "fci"]
    header = r"""
\begin{tabular}{S[table-format=2.0]SS[table-format=2.0]S[table-format=3.5]S[table-format=3.5]S[table-format=3.5]}%
\hline\hline
{$N$} & {$\omega$} & {$K$} & {IM-SRG(2)} & {CCSD} & {FCI} \\
"""[1:]
    c = d["energy"]

    s = []
    s.append(header)
    for num_particles, case in cases:
        s.append("\\hline\n")
        for freq, num_shells in case:
            row = [num_particles, freq, num_shells]
            for method in methods:

                def get():  # to allow early returns
                    key = (num_shells, num_particles, freq, method)
                    if key not in d.index:
                        return None
                    return d.loc[key]["energy"]

                value = get()
                if value is None:
                    if ("imsrg" in method and
                        (num_shells, num_particles, freq) in KNOWN_NC_IMSRG):
                        value = "n.c."
                    if ("ccsd" in method and
                        (num_shells, num_particles, freq) in KNOWN_NC_CCSD):
                        value = "n.c."
                row.append(render_entry(value))
            s.append(" & ".join(map(str, row)) + " \\\\\n")
    s.append("\\hline\\hline\n\\end{tabular}")

    with open(path, "w") as f:
        f.write("".join(s))
    return d
Beispiel #12
0
def plot_TSNE(fig_name):
    """
    plot a figure for 2D t-SNE dimension reduction
    :param fig_name: saved figure name
    :return: figure
    """
    dir = "log/peps mini"
    pattern = r'(internal|access|lock)\\\d{1,2}.csv$'
    pattern_valid = r'(3|6|9|12).csv$'
    utils.construct_set(dir, pattern, pattern_valid)
    X, y = utils.load_all()
    utils.plot_TSNE(X, y)
    plt.title(fig_name)
    if not os.path.exists(dir_fig):
        os.makedirs(dir_fig)
    plt.savefig(dir_fig + '/' + fig_name + '.png')
Beispiel #13
0
def plot(label, num_filled, freq, num_shells_range, interaction="normal"):
    d_dmc = utils.load_all_dmc()
    d_dmc = d_dmc[(d_dmc["interaction"] == interaction)
                  & (d_dmc["label"] == label) &
                  (d_dmc["num_filled"] == num_filled) &
                  (d_dmc["freq"] == freq)]
    d_dmc = d_dmc.set_index(["num_particles", "freq"])
    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    d = d[(d["method"] != "imsrg[f]+eom[n]")
          & (d["method"] != "magnus_quads+eom") &
          (d["interaction"] == interaction) & (d["label"] == label) &
          (d["num_filled"] == num_filled) &
          (d["num_shells"] >= num_shells_range[0]) &
          (d["num_shells"] <= num_shells_range[1]) & (d["freq"] == freq)]
    num_particles = num_filled * (num_filled + 1)
    energy_type = {
        "ground": "ground state",
        "add": "addition",
        "rm": "removal"
    }[label]
    fig, ax = plt.subplots()
    fig.set_size_inches((3.2, 2.7))
    base_markersize = 5
    for method, case in d.groupby("method"):
        case = case.sort_values("num_shells")
        xs = case["num_shells"].astype(int)
        ys = case["energy"]
        marker = utils.METHOD_MARKER[method]
        style = {
            "marker":
            marker,
            "markerfacecolor":
            "none",
            "markersize":
            (utils.MARKERSIZE_CORRECTION.get(marker, 1.0) * base_markersize),
            "color":
            utils.METHOD_COLOR[method],
            "label":
            utils.METHOD_LABEL[method],
        }
        ax.plot(xs, ys, **style)
Beispiel #14
0
def load_full_fit_data(fit_count=DEFAULT_FIT_COUNT, maxfev=DEFAULT_MAXFEV):
    '''Load fit data from file if available.  Otherwise calculate the fits.'''
    fn = "fit_data.fit_count={fit_count}_maxfev={maxfev}.txt".format(
        **locals())
    try:
        return utils.load_table(fn)
    except OSError:
        pass

    sys.stderr.write("Fit data has not yet been calculated.  "
                     "This may take a few minutes...\n")
    sys.stderr.flush()
    d = utils.filter_preferred_ml(utils.load_all())
    d = d[~d["method"].isin(["imsrg[f]+eom[n]"])]
    with multiprocessing.Pool(4) as p:
        results_s, missing_num_shells = zip(*p.map(
            functools.partial(
                gather_fit_data, fit_count=fit_count, maxfev=maxfev),
            tuple(
                d.groupby([
                    "label", "interaction", "num_filled", "freq", "method"
                ]))))
    results = itertools.chain(*results_s)

    missing_fn = ("fits_missing_points."
                  "fit_count={fit_count}_maxfev={maxfev}.log".format(
                      **locals()))
    utils.save_table(missing_fn.format(**locals()),
                     pd.DataFrame.from_records(missing_num_shells))
    sys.stderr.write("Missing data points logged to: {}\n".format(missing_fn))
    sys.stderr.flush()

    d = pd.DataFrame.from_records(results)
    num_failed = (d["fit_method"] == "fixedab").sum()
    if num_failed:
        sys.stderr.write("{} out of {} fits failed\n".format(
            num_failed, len(d)))
        sys.stderr.flush()

    utils.save_table(fn, d)
    return d
Beispiel #15
0
def main():
    # get param
    parser = argparse.ArgumentParser("PP simulator")
    parser.add_argument('--param-file', type=str, default='parameters', help="")
    parser.add_argument('--result', type=str, default='result', help="")
    parser.add_argument("--fit_epochs", type=int, default=20)
    parser.add_argument("--only_simu", action='store_true')
    args = parser.parse_args()

    # Load params
    #param = json.load(open(args.param_file, "rt"))
    params = utils.load_all([args.param_file])[0]

    os.makedirs(args.result, exist_ok=True)

    # Step 1 : simulation
    tauList = run_simu(args, params, 2)

    if args.only_simu:
        return

    # Step 2 : fitting
    run_fitting(args, params, tauList)
Beispiel #16
0
def main(label):
    num_shells_range = {
        6: [3.5, 14.5],
        12: [4.5, 16.5],
        20: [6.5, 16.5],
        30: [9.5, 16.5],
        42: [11.5, 20.5],
        56: [14.5, 20.5],
    }
    num_particles_ticks = [6, 30, 56]
    LEGEND_FACET_IDX = 2

    if label == "ground":
        freq_ticks = [0.28, 1.0]
        methods = ["mp2", "imsrg", "ccsd", "fci"]
        fn = "../Manuscript/fig-gs2.pdf"
    else:
        freq_ticks = [0.28, 1.0]        # 0.28 needed to show DMC results
        fn = "../Manuscript/fig-{}2.pdf".format(label)
        methods = ["imsrg+qdpt3", "imsrg+eom", "ccsd+eom"]

    d = utils.load_all()
    d_dmc = utils.load_all_dmc()
    d = utils.filter_preferred_ml(d)
    del d["ml"]
    d = d[d["interaction"] == "normal"]
    del d["interaction"]
    d = d[d["label"] == label]
    d_dmc = d_dmc[d_dmc["label"] == label]
    del d["label"]
    del d_dmc["label"]
    del d["num_filled"]
    d_dmc = d_dmc.set_index(["num_particles", "freq"])

    facet_x = {
        "col": "num_particles",
        "symbol": "N",
        "ticks": num_particles_ticks,
    }
    facet_y = {
        "col": "freq",
        "symbol": "\omega",
        "ticks": freq_ticks,
    }
    facet_to_num_particles_freq = lambda x, y: (x, y)

    has_dmc = False
    width = 6.5
    height = 3
    base_markersize = 5.0
    fig = plt.figure(figsize=(width, height))
    gs = matplotlib.gridspec.GridSpec(len(facet_y["ticks"]),
                                      len(facet_x["ticks"]))
    for (fct_x, fct_y), d in d.groupby([facet_x["col"], facet_y["col"]]):
        num_particles, freq = facet_to_num_particles_freq(fct_x, fct_y)
        try:
            gi = (facet_x["ticks"].index(fct_x) +
                  facet_y["ticks"].index(fct_y) * len(facet_x["ticks"]))
        except ValueError:
            continue
        if gi == LEGEND_FACET_IDX:
            continue
        ax = fig.add_subplot(gs[gi])

        try:
            sel_dmc = d_dmc.loc[(num_particles, freq)]
        except KeyError:
            pass
        else:
            has_dmc = True
            ax.axhline(sel_dmc["energy"],
                       color=utils.METHOD_COLOR["dmc"],
                       linestyle=utils.DMC_LINESTYLE)

        for method, d in d.groupby("method"):
            if method not in methods:
                continue

            d = d[(d["num_shells"] >= num_shells_range[num_particles][0]) &
                  (d["num_shells"] <= num_shells_range[num_particles][1])]
            d = d.sort_values(["num_shells"])
            marker = utils.METHOD_MARKER[method]
            ax.plot(d["num_shells"], d["energy"],
                    marker=marker,
                    markerfacecolor="none",
                    markersize=(utils.MARKERSIZE_CORRECTION.get(marker, 1.0) *
                                base_markersize),
                    color=utils.METHOD_COLOR[method])

        title = ("${} = {}$\n${} = {}$"
                 .format(facet_x["symbol"], fct_x,
                         facet_y["symbol"], fct_y))
        ax.text(1.0 - 2.65 / width, 0.6, title,
                color="#505050",
                horizontalalignment="left",
                transform=ax.transAxes,
                fontsize=12)
        ax.set_xlim(num_shells_range[num_particles])
    fig.text(0.5, 0.05 / height, "$K$ (number of shells)",
             horizontalalignment="center",
             verticalalignment="bottom",
             transform=ax.transAxes)
    fig.text(0.05 / width, 0.5, "${}$".format(utils.ENERGY_SYMBOL[label]),
             horizontalalignment="left",
             verticalalignment="center",
             transform=ax.transAxes,
             rotation="vertical")

    # phantom lines to configure the legend
    markersize = (utils.MARKERSIZE_CORRECTION.get(marker, 1.0) *
                  base_markersize)
    lines = [matplotlib.lines.Line2D([], [],
                                     marker=utils.METHOD_MARKER[method],
                                     markersize=markersize,
                                     color=utils.METHOD_COLOR[method],
                                     label=utils.METHOD_LABEL[method])
             for method in methods]
    if has_dmc:
        lines.append(matplotlib.lines.Line2D([], [],
                                             linestyle=utils.DMC_LINESTYLE,
                                             color=utils.METHOD_COLOR["dmc"],
                                             label=utils.METHOD_LABEL["dmc"]))
    ax = fig.add_subplot(gs[LEGEND_FACET_IDX])
    ax.axis("off")
    ax.legend(handles=lines, loc="center", frameon=False,
              bbox_to_anchor=(0.5, 0.5 - 0.1 / height))

    left_margin = 0.1
    right_margin = 0.0
    top_margin = 0.0
    bottom_margin = 0.1
    gs.tight_layout(fig, rect=[left_margin / width,
                               bottom_margin / height,
                               1.0 - right_margin / width,
                               1.0 - top_margin / height])
    utils.savefig(fig, fn=fn)
Beispiel #17
0
def signal_handler_sigusr2(sig, frame):
    if events_server_pid is not None:
        os.kill(events_server_pid, signal.SIGUSR2)
    utils.load_all()
Beispiel #18
0
import utils

if __name__ == '__main__':

    dir = "log/peps normal"
    pattern = r'(left|right|front|back|start|trunk|lock)\\\d{1,2}.csv$'
    pattern_valid = r'(3|6|9|12).csv$'
    utils.construct_set(dir, pattern, pattern_valid, filter=1)
    utils.save_to_csv()

    X, y = utils.load_all()
    X_train, X_valid, y_train, y_valid = utils.load_train_valid()

    # compare train result
    methods = ["Logistic", "LDA", "QDA", "KNN", "SVM", "RF", "GBM", "MLP"]
    params = [
        None, None, None, {
            "n_neighbors": 10
        }, {
            "C": 0.25,
            "gamma": 0.5
        }, {
            "max_features": 2,
            "n_estimators": 100
        }, {
            "n_estimators": 400,
            "max_depth": 3
        }, {
            "hidden_layer_sizes": (16, 8)
        }
    ]
Beispiel #19
0
def signal_handler_sigusr2(sig, frame):
    utils.load_all()
def plot(fit_count=5, log=False, maxfev=0, plot_type="scatter",
         stat="err", hf=False):
    dorig = utils.filter_preferred_ml(utils.load_all())

    d_good = utils.load_table("fits_good.txt")
    d_good = d_good.groupby(
        ["interaction", "label", "freq", "num_filled", "method"]
    ).first()

    d = gather_fit_data(fit_count=fit_count, maxfev=maxfev)

    d = d[d["interaction"] == "normal"]
    # d = d[d["label"] == "add"]
    # d = d[d["method"] == "imsrg"]
    # d = d[d["num_filled"] == 5]
    # d = d[d["freq"] == 0.1]
    d = d[d["fit_method"] != "fixedab"]

    doriggrps = dorig.groupby(["interaction", "label", "freq",
                               "num_filled", "method"])

    d["rel_constant_err"] = d["constant_err"] / d["constant"]
    d["rel_best_constant_err"] = d["best_constant_err"] / d["best_constant"]
    d["label_is_ground"] = d["label"] == "ground"
    d["good"] = d.apply(lambda r: d_good.loc[
        (r["interaction"], r["label"], r["freq"],
         r["num_filled"], r["method"])]["good"], axis=1)
    d["rel_chi"] = d["chisq"]**.5 / d["constant"]
    d["rel_reduced_chi"] = d["rel_chi"] / (fit_count - 3)
    d["rel_best_chisq"] = d["best_chisq"]**.5 / d["best_constant"]
    d["rel_best_reduced_chisq"] = d["rel_best_chisq"] / (fit_count - 3)
    d = d[(d["rel_best_reduced_chisq"] < 1e-6)]
    d["fixedab_with_hf"] = (
        ((d["fit_method"] == "fixedab") ==
         (d["method"].isin(["hf", "hf+qdpt3"]))) |
        (d["fit_method"] == "full")
    )

    color_col = "method"
    bin_transform = TRANSFORM_ID
    bin_transform = TRANSFORM_LOG_ABS

    if color_col in ["exponent", "rel_dist", "rel_constant_err",
                     "rel_best_constant_err", "rel_best_chisq",
                     "rel_chi", "rel_reduced_chi", "chi_ratio"]:
        num_bins = 16
        d = d.replace([np.inf, -np.inf], np.nan).dropna(subset=[color_col])
        binf = bin_transform[0]
        bininvf = bin_transform[1]
        color_bins = pd.cut(binf(abs(d[color_col])), num_bins)
        d["color_bin_start"] = color_bins.map(
            lambda bin: bininvf(parse_bin(bin)[0]))
        d["color_bin_stop"] = color_bins.map(
            lambda bin: bininvf(parse_bin(bin)[1]))
        color_bin_cols = ["color_bin_start", "color_bin_stop"]
    else:
        color_bin_cols = [color_col]
    max_bins = len(d[color_bin_cols[0]].unique())

    fig, ax = plt.subplots()

    def on_pick_event(event):
        x = list(event.artist.get_xdata()[event.ind])[0]
        y = list(event.artist.get_ydata()[event.ind])[0]
        sel = d[(abs(d["x"] - x) <= 1e-20) &
                (abs(d["y"] - y) <= 1e-20)]
        print(sel.transpose().to_csv())
        if len(sel) != 1:
            print('>> not found <<')
            return

        sel = sel.iloc[0]
        grp = doriggrps.get_group((sel["interaction"], sel["label"],
                                   sel["freq"], sel["num_filled"],
                                   sel["method"]))
        fig, ax = plt.subplots(2)
        ax[0].plot(grp["num_shells"], grp["energy"], "x")
        fit_start = sel["fit_stop"] + 1 - fit_count
        ax[0].axvspan(fit_start, sel["fit_stop"], color="#cccccc")
        xs = np.linspace(grp["num_shells"].min(), grp["num_shells"].max())
        ax[0].plot(xs,
                   sel["coefficient"] * xs ** sel["exponent"]
                   + sel["constant"])
        subgrp = grp[grp["num_shells"].between(
            fit_start-0.1, sel["fit_stop"]+0.1)]
        last_constant = sel["constant"]
        last_constant_err = sel["constant_err"]

        def random_weight(count):
            weights = np.zeros(count)
            for i in range(count):
                weights[np.random.randint(0, count)] += 1
            return weights

        p0 = [sel["coefficient"], sel["exponent"], sel["constant"]]
        p = p0
        x = subgrp["num_shells"]
        y = subgrp["energy"]
        constants = []
        constants.append(p[2])

        print(f"x = np.array({list(x)})")
        print(f"y = np.array({list(y)})")

        ax[1].plot(x, (p[0] * x ** p[1] + p[2] - y), "-x")
        ax[1].axhline(0.0, linestyle=":")

        for i in range(10):
            count = len(x)
            weights = random_weight(count) + 1e-99
            if sum(weights > 0.1) <= 3: # can't fit with this few points
                continue
            try:
                p, cov = scipy.optimize.curve_fit(
                    lambda x, a, b, c: a * x ** b + c,
                    x, y,
                    sigma=1.0 / weights ** 0.5,
                    p0=p0, maxfev=100000)
            except RuntimeError as e:
                print(e)
                continue
            chisq = np.average((p[0] * x ** p[1] + p[2] - y) ** 2,
                               weights=weights) * len(x)
            constant = p[2]
            constant_err = cov[2, 2] ** 0.5
            constants.append(p[2])
            last_constant = constant
            last_constant_err = constant_err
        print("result", np.mean(constants), np.std(constants))
        print("rel", np.std(constants) / np.mean(constants))
        ax[0].set_ylim([max(ax[0].get_ylim()[0], 0.0),
                        min(ax[0].get_ylim()[1], np.max(y))])
        ax[0].plot(xs, p[0] * xs ** p[1] + p[2], ":", color="lime")

    fig.canvas.mpl_connect("pick_event", on_pick_event)

    d["quality"] = np.log10(d["constant_err"]/d["chisq"]**0.5)

    # hf has unique behaviors (what about mp2?)
    if hf:
        d = d[d["method"] == "hf"]
    else:
        d = d[d["method"] != "hf"]
        if stat == "err":
            d = d[d["quality"] > 0]

    d["y"] = d["rel_discrep"] / d["rel_constant_err"]
    if stat == "hessian":
        d["x"] = d["quality"]
    elif stat == "err":
        d["x"] = np.log10(d["rel_constant_err"])
    else:
        assert False

    d["y_err"] = d["rel_discrep_err"] / d["rel_discrep"] * d["y"]

    d = d[(d["rel_constant_err"] > 0) & (d["rel_constant_err"] < np.inf)]
    if plot_type == "contour":

        if hf:
            hf_suffix = "HF"
        else:
            hf_suffix = "non-HF"
        # ranged = mesh; lim = view
        if stat == "err":
            if hf:
                nx = 20
                ny = 20
                xrange = (-7, -1)
                yrange = (-5, 5)
                xlim = (-6, -2)
                ylim = (-4, 4)
                title = ("discrepancy vs fit uncertainty "
                         f"({hf_suffix})")
            else:
                nx = 20
                ny = 40
                xrange = (-7, -1)
                yrange = (-50, 50)
                xlim = (-6, -2)
                ylim = (-40, 40)
                title = ("discrepancy vs fit uncertainty "
                         f"(filtered: Q > 0, {hf_suffix})")
            xlabel = r"$\log_{10}\left(\frac{\sigma_c}{c}\right)$"
            ylabel = r"$\frac{\varepsilon}{\sigma_c}$"
        elif stat == "hessian":
            if hf:
                nx = 20
                ny = 40
                xrange = (-0.6, 1.5)
                yrange = (-10, 10)
                xlim = (-0.4, 1.1)
                ylim = (-10, 10)
            else:
                nx = 20
                ny = 40
                xrange = (-0.6, 2.1)
                yrange = (-200, 200)
                xlim = (-0.4, 1.7)
                ylim = (-150, 150)
            title = ("spread of “actual” discrepancy vs quality "
                     f"({hf_suffix})")
            xlabel = (r"$Q = \log_{10}\left(\frac{\sigma_c}"
                       r"{\sqrt{\mathtt{RSS}}}\right)$")
            ylabel = r"$\frac{\varepsilon}{\sigma_c}$"
        else:
            assert False
        ax.plot(d["x"], d["y"], "o", markersize=1, picker=3,
                color="white", markeredgewidth=0)
        dx = (xrange[1] - xrange[0]) / (nx - 1)
        h, x, y = np.histogram2d(d["x"], d["y"], bins=(nx, ny - 1),
                                 range=((xrange[0] - 0.5 * dx,
                                         xrange[1] + 0.5 * dx),
                                        yrange))
        ch = np.concatenate([np.zeros((nx, 1)),
                             np.cumsum(h, axis=1)],
                            axis=1)
        z = ch / ch[..., -1, np.newaxis]
        x, y = np.meshgrid(0.5 * (x[1:] + x[:-1]), y, indexing="ij")
        levels = np.linspace(-2.0, 2.0, 5)
        levels = 0.5 + 0.5 * scipy.special.erf(2.0 ** -0.5 * levels)
        ax.axhline(-1.0, linestyle="--", color="white", linewidth=0.5)
        ax.axhline(1.0, linestyle="--", color="white", linewidth=0.5)
        ax.contour(x, y, z,
                   levels=levels,
                   colors="white",
                   alpha=0.3)
        cs = ax.contourf(x, y, z,
                         levels=np.linspace(0.0, 1.0, 300),
                         # note: translucent cmaps tend to cause artifacts
                         cmap=CMAP_FOLDED_VIRIDIS,
                         linestyle=":")
        for c in cs.collections: # http://stackoverflow.com/a/32911283
            c.set_edgecolor("face")
        fig.colorbar(cs)
        ax.set_title(title)
        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)
        ax.set_xlim(xlim)
        ax.set_ylim(ylim)

    elif plot_type == "scatter":

        cmap = utils.CMAP_RAINBOW
        for i, (bin, g) in enumerate(sorted(d.groupby(color_bin_cols))):
            color = cmap(float(i) / max_bins)
            ax.plot(g["x"], g["y"], ".",
                    label=str(bin),
                    color=color,
                    markersize=10,
                    markeredgewidth=0,
                    alpha=0.5,
                    picker=2)
        ax.legend()

    fn = f"fit-predictiveness-{plot_type}-{fit_count}-{stat}-{hf}"
    fig.tight_layout()
    utils.savefig(fig, fn)
Beispiel #21
0
def signal_handler_sigusr2(sig, frame):
    if events_server_pid is not None:
        os.kill(events_server_pid, signal.SIGUSR2)
    utils.load_all()
Beispiel #22
0
# Generates ../FigureFiles/fig-by-freq-*.svg from the data files.
import argparse, itertools, os, sys
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import utils

p = argparse.ArgumentParser()
p.add_argument("-i", "--interactive", action="store_true")
p.add_argument("-t", "--title", action="store_true")
p.add_argument("-int", "--interaction", default="normal")
p.add_argument("label", metavar="type", help="ground, add, or rm")
kwargs = vars(p.parse_args())
plt.rcParams["interactive"] = kwargs["interactive"]
with utils.plot(__file__):
    d = utils.load_all()
    num_shells = 10
    num_filled = 2
    interaction = kwargs["interaction"]
    label = kwargs["label"]
    ml = utils.label_num_filled_to_ml(label, num_filled)
    d = d[(d["method"] != "imsrg[f]+eom[n]") &
          (d["method"] != "magnus_quads+eom") &
          (d["interaction"] == interaction) &
          (d["label"] == label) &
          (d["num_shells"] == num_shells) &
          (d["num_filled"] == num_filled) &
          # filter out higher frequencies because they stretch the plot too much
          (d["freq"] <= 1.0) &
          (d["ml"] == ml)]
    num_particles = num_filled * (num_filled + 1)
Beispiel #23
0
def signal_handler_sigusr2(sig, frame):
    utils.load_all()
Beispiel #24
0
def plot(label,
         freq,
         num_filled,
         fit_start,
         fit_stop=np.inf,
         fit_ranges={},
         interaction="normal",
         methods=None,
         badness_threshold=LOGDERIV_BADNESS_THRESHOLD,
         plot=True,
         maxfev=0):
    '''label: ground, add, or rm.

    fit_ranges: {method: (start, stop)}
    Used to adjust the fit_range of a specific method (overrides fit_start and
    fit_stop).'''

    d_dmc = utils.load_all_dmc()
    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    d = d[~d["method"].isin(["imsrg[f]+eom[n]"])]

    # filters
    d = d[d["interaction"] == interaction]
    d = d[d["num_filled"] == num_filled]
    d = d[d["freq"] == freq]
    d = d[d["label"] == label]
    if methods is not None:
        d = d[d["method"].isin(methods)]

    if label == "ground":
        e_sym = "E/N"
        e_text = "energy per particle"
        d["energy"] /= d["num_particles"]
        d_dmc["energy"] /= d_dmc["num_particles"]
        d_dmc["energy_err"] /= d_dmc["num_particles"]
    else:
        e_sym = "ε"
        e_text = "energy"

    default_fit_range = (fit_start, fit_stop)
    fit_results = plot_fits(
        plot=plot,
        data=d,
        get_fit_range=lambda method: fit_ranges.get(method, default_fit_range),
        badness_threshold=badness_threshold,
        x_col="num_shells",
        x_label="K (number of shells)",
        y_col="energy",
        y_label=f"{e_sym} ({e_text})",
        absdydx_label=f"|∂{e_sym}/∂K|",
        title_cols=["label", "num_filled", "num_particles", "freq"],
        get_title="{label}, N={num_particles}, ω={freq}".format,
        get_fn="fit-{label}-{num_filled}-{freq}".format,
        color_cols=["method"],
        get_color=utils.METHOD_COLOR.get,
        get_color_label=utils.METHOD_LABEL.get,
        get_dmc=utils.filter_eq(d_dmc, ["label", "num_filled", "freq"],
                                check_unused_kwargs=False),
        dmc_label="DMC",
        dmc_yerr_col="energy_err",
        maxfev=maxfev,
    )
    results = []
    for method, fit_result in sorted(fit_results.items()):
        results.append({
            "interaction": interaction,
            "label": label,
            "freq": freq,
            "num_filled": num_filled,
            "method": method,
            "fit_result": fit_result,
        })
    return results
def signal_handler_sigusr2(sig, frame):
    utils.load_all()
    utils.restart_webhook_pool()
Beispiel #26
0
def plot(label, freq, num_filled, fit_start, fit_stop=np.inf,
         fit_ranges={}, interaction="normal", methods=None,
         badness_threshold=LOGDERIV_BADNESS_THRESHOLD, plot=True):
    '''label: ground, add, or rm.

    fit_ranges: {method: (start, stop)}
    Used to adjust the fit_range of a specific method (overrides fit_start and
    fit_stop).'''

    d_dmc = utils.load_all_dmc()
    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    d = d[~d["method"].isin(["imsrg[f]+eom[n]"])]

    # filters
    d = d[d["interaction"] == interaction]
    d = d[d["num_filled"] == num_filled]
    d = d[d["freq"] == freq]
    d = d[d["label"] == label]
    if methods is not None:
        d = d[d["method"].isin(methods)]

    if label == "ground":
        e_sym = "E/N"
        e_text = "energy per particle"
        d["energy"] /= d["num_particles"]
        d_dmc["energy"] /= d_dmc["num_particles"]
        d_dmc["energy_err"] /= d_dmc["num_particles"]
    else:
        e_sym = "ε"
        e_text = "energy"

    default_fit_range = (fit_start, fit_stop)
    fit_results = plot_fits(
        plot=plot,
        data=d,
        get_fit_range=lambda method: fit_ranges.get(method, default_fit_range),
        badness_threshold=badness_threshold,
        x_col="num_shells",
        x_label="K (number of shells)",
        y_col="energy",
        y_label=f"{e_sym} ({e_text})",
        absdydx_label=f"|∂{e_sym}/∂K|",
        title_cols=["label", "num_filled", "num_particles", "freq"],
        get_title="{label}, N={num_particles}, ω={freq}".format,
        get_fn="fit-{label}-{num_filled}-{freq}".format,
        color_cols=["method"],
        get_color=utils.METHOD_COLOR.get,
        get_color_label=utils.METHOD_LABEL.get,
        get_dmc=utils.filter_eq(d_dmc, ["label", "num_filled", "freq"],
                                check_unused_kwargs=False),
        dmc_label="DMC",
        dmc_yerr_col="energy_err",
    )
    results = []
    for method, fit_result in sorted(fit_results.items()):
        results.append({
            "interaction": interaction,
            "label": label,
            "freq": freq,
            "num_filled": num_filled,
            "method": method,
            "fit_result": fit_result,
        })
    return results
Beispiel #27
0
def save_table(path,
               label,
               num_shells=NUM_SHELLS,
               num_particles=[6, 12, 20, 30, 42, 56],
               freqs=[0.1, 0.28, 1.0]):
    d = utils.load_all()
    d = utils.filter_preferred_ml(d)
    del d["ml"]
    d = d[d["interaction"] == "normal"]
    del d["interaction"]
    d = d[d["label"] == label]
    del d["label"]
    del d["num_filled"]
    d = d.set_index(["num_shells", "num_particles", "freq", "method"])

    if label == "ground":
        methods = ["hf", "mp2", "imsrg", "ccsd"]
        header = r"""
\begin{tabular}{S[table-format=2.0]SS[table-format=2.0]S[table-format=3.5]S[table-format=3.5]S[table-format=3.5]S[table-format=3.5]}%
\hline\hline
{$N$} & {$\omega$} & {$K$} & {HF} & {MP2} & {IM-SRG(2)} & {CCSD} \\
"""[1:]
    else:
        methods = ["hf+qdpt3", "imsrg+qdpt3", "imsrg+eom", "ccsd+eom"]
        header = r"""
\begin{tabular}{S[table-format=2.0]SS[table-format=2.0]S[table-format=3.5]S[table-format=3.5]S[table-format=3.5]S[table-format=3.5]}%
\hline\hline
{$N$} & {$\omega$} & {$K$} & {HF} & {IM-SRG(2)} & {IMSRG(2)} & {CCSD} \\
{} & {} & {} & {+QDPT3} & {+QDPT3} & {+EOM} & {+EOM} \\
"""[1:]
    c = d["energy"]

    s = []
    s.append(header)
    for num_shells, num_particles in zip(num_shells, num_particles):
        s.append("\\hline\n")
        for freq in freqs:
            row = [num_particles, freq, num_shells]
            for method in methods:

                def get():  # to allow early returns
                    key = (num_shells, num_particles, freq, method)
                    if key not in d.index:
                        return None
                    return d.loc[key]["energy"]

                value = get()
                if value is None:
                    if ("imsrg" in method and
                        (num_shells, num_particles, freq) in KNOWN_NC_IMSRG):
                        value = "n.c."
                    if ("ccsd" in method and
                        (num_shells, num_particles, freq) in KNOWN_NC_CCSD):
                        value = "n.c."
                row.append(render_entry(value))
            s.append(" & ".join(map(str, row)) + " \\\\\n")
    s.append("\\hline\\hline\n\\end{tabular}")

    with open(path, "w") as f:
        f.write("".join(s))
    return d
Beispiel #28
0
def signal_handler_sigusr2(sig, frame):
    utils.load_all()
    utils.restart_webhook_pool()
def plot(fit_count=fits.DEFAULT_FIT_COUNT, log=False,
         maxfev=fits.DEFAULT_MAXFEV, plot_type="scatter",
         stat="err", hf=False):
    dorig = utils.filter_preferred_ml(utils.load_all())

    d_good = utils.load_table("fits_good.txt")
    d_good = d_good.groupby(
        ["interaction", "label", "freq", "num_filled", "method"]
    ).first()

    d = fits.load_predictive_data(fit_count=fit_count, maxfev=maxfev)

    d = d[d["interaction"] == "normal"]
    # d = d[d["label"] == "add"]
    # d = d[d["method"] == "imsrg"]
    # d = d[d["num_filled"] == 5]
    # d = d[d["freq"] == 0.1]
    d = d[d["fit_method"] != "fixedab"]

    doriggrps = dorig.groupby(["interaction", "label", "freq",
                               "num_filled", "method"])

    d["rel_constant_err"] = d["constant_err"] / d["constant"]
    d["rel_best_constant_err"] = d["best_constant_err"] / d["best_constant"]
    d["label_is_ground"] = d["label"] == "ground"
    d["good"] = d.apply(functools.partial(is_good, d_good), axis=1)
    d["rel_chi"] = d["chisq"]**.5 / d["constant"]
    d["rel_reduced_chi"] = d["rel_chi"] / (fit_count - 3)
    d["rel_best_chisq"] = d["best_chisq"]**.5 / d["best_constant"]
    d["rel_best_reduced_chisq"] = d["rel_best_chisq"] / (fit_count - 3)
    d = d[(d["rel_best_reduced_chisq"] < 1e-6)]
    d["fixedab_with_hf"] = (
        ((d["fit_method"] == "fixedab") ==
         (d["method"].isin(["hf", "hf+qdpt3"]))) |
        (d["fit_method"] == "full")
    )

    color_col = "method"
    bin_transform = TRANSFORM_ID
    bin_transform = TRANSFORM_LOG_ABS

    if color_col in ["exponent", "rel_dist", "rel_constant_err",
                     "rel_best_constant_err", "rel_best_chisq",
                     "rel_chi", "rel_reduced_chi", "chi_ratio"]:
        num_bins = 16
        d = d.replace([np.inf, -np.inf], np.nan).dropna(subset=[color_col])
        binf = bin_transform[0]
        bininvf = bin_transform[1]
        color_bins = pd.cut(binf(abs(d[color_col])), num_bins)
        d["color_bin_start"] = color_bins.map(
            lambda bin: bininvf(parse_bin(bin)[0]))
        d["color_bin_stop"] = color_bins.map(
            lambda bin: bininvf(parse_bin(bin)[1]))
        color_bin_cols = ["color_bin_start", "color_bin_stop"]
    else:
        color_bin_cols = [color_col]
    max_bins = len(d[color_bin_cols[0]].unique())

    fig, ax = plt.subplots()

    def on_pick_event(event):
        x = list(event.artist.get_xdata()[event.ind])[0]
        y = list(event.artist.get_ydata()[event.ind])[0]
        sel = d[(abs(d["x"] - x) <= 1e-20) &
                (abs(d["y"] - y) <= 1e-20)]
        print(sel.transpose().to_csv())
        if len(sel) != 1:
            print('>> not found <<')
            return

        sel = sel.iloc[0]
        grp = doriggrps.get_group((sel["interaction"], sel["label"],
                                   sel["freq"], sel["num_filled"],
                                   sel["method"]))
        fig, ax = plt.subplots(2)
        ax[0].plot(grp["num_shells"], grp["energy"], "x")
        fit_start = sel["fit_stop"] + 1 - fit_count
        ax[0].axvspan(fit_start, sel["fit_stop"], color="#cccccc")
        xs = np.linspace(grp["num_shells"].min(), grp["num_shells"].max())
        ax[0].plot(xs,
                   sel["coefficient"] * xs ** sel["exponent"]
                   + sel["constant"])
        subgrp = grp[grp["num_shells"].between(
            fit_start-0.1, sel["fit_stop"]+0.1)]
        last_constant = sel["constant"]
        last_constant_err = sel["constant_err"]

        def random_weight(count):
            weights = np.zeros(count)
            for i in range(count):
                weights[np.random.randint(0, count)] += 1
            return weights

        p0 = [sel["coefficient"], sel["exponent"], sel["constant"]]
        p = p0
        x = subgrp["num_shells"]
        y = subgrp["energy"]
        constants = []
        constants.append(p[2])

        print(f"x = np.array({list(x)})")
        print(f"y = np.array({list(y)})")

        ax[1].plot(x, (p[0] * x ** p[1] + p[2] - y), "-x")
        ax[1].axhline(0.0, linestyle=":")

        for i in range(10):
            count = len(x)
            weights = random_weight(count) + 1e-99
            if sum(weights > 0.1) <= 3: # can't fit with this few points
                continue
            try:
                p, cov = scipy.optimize.curve_fit(
                    lambda x, a, b, c: a * x ** b + c,
                    x, y,
                    sigma=1.0 / weights ** 0.5,
                    p0=p0, maxfev=100000)
            except RuntimeError as e:
                print(e)
                continue
            chisq = np.average((p[0] * x ** p[1] + p[2] - y) ** 2,
                               weights=weights) * len(x)
            constant = p[2]
            constant_err = cov[2, 2] ** 0.5
            constants.append(p[2])
            last_constant = constant
            last_constant_err = constant_err
        print("result", np.mean(constants), np.std(constants))
        print("rel", np.std(constants) / np.mean(constants))
        ax[0].set_ylim([max(ax[0].get_ylim()[0], 0.0),
                        min(ax[0].get_ylim()[1], np.max(y))])
        ax[0].plot(xs, p[0] * xs ** p[1] + p[2], ":", color="lime")

    fig.canvas.mpl_connect("pick_event", on_pick_event)

    d["quality"] = np.log10(d["constant_err"]/d["chisq"]**0.5)

    # hf has unique behaviors (what about mp2?)
    if hf:
        d = d[d["method"] == "hf"]
    else:
        d = d[d["method"] != "hf"]
        if stat == "err":
            d = d[d["quality"] > 0]

    d["y"] = d["rel_discrep"] / d["rel_constant_err"]
    if stat == "hessian":
        d["x"] = d["quality"]
    elif stat == "err":
        d["x"] = np.log10(d["rel_constant_err"])
    else:
        assert False

    d["y_err"] = d["rel_discrep_err"] / d["rel_discrep"] * d["y"]

    d = d[(d["rel_constant_err"] > 0) & (d["rel_constant_err"] < np.inf)]
    if plot_type == "contour":

        if hf:
            hf_suffix = "HF"
        else:
            hf_suffix = "non-HF"
        # ranged = mesh; lim = view
        if stat == "err":
            if hf:
                nx = 20
                ny = 20
                xrange = (-7, -1)
                yrange = (-5, 5)
                xlim = (-6, -2)
                ylim = (-4, 4)
                title = ("discrepancy vs fit uncertainty "
                         f"({hf_suffix})")
            else:
                nx = 20
                ny = 40
                xrange = (-7, -1)
                yrange = (-50, 50)
                xlim = (-6, -2)
                ylim = (-40, 40)
                title = ("discrepancy vs fit uncertainty "
                         f"(filtered: Q > 0, {hf_suffix})")
            xlabel = r"$\log_{10}\left(\frac{\sigma_c}{c}\right)$"
            ylabel = r"$\frac{\varepsilon}{\sigma_c}$"
        elif stat == "hessian":
            if hf:
                nx = 20
                ny = 40
                xrange = (-0.6, 1.5)
                yrange = (-10, 10)
                xlim = (-0.4, 1.1)
                ylim = (-10, 10)
            else:
                nx = 20
                ny = 40
                xrange = (-0.6, 2.1)
                yrange = (-200, 200)
                xlim = (-0.4, 1.7)
                ylim = (-150, 150)
            title = ("spread of “actual” discrepancy vs quality "
                     f"({hf_suffix})")
            xlabel = (r"$Q = \log_{10}\left(\frac{\sigma_c}"
                       r"{\sqrt{\mathtt{RSS}}}\right)$")
            ylabel = r"$\frac{\varepsilon}{\sigma_c}$"
        else:
            assert False
        ax.plot(d["x"], d["y"], "o", markersize=1, picker=3,
                color="white", markeredgewidth=0)
        dx = (xrange[1] - xrange[0]) / (nx - 1)
        h, x, y = np.histogram2d(d["x"], d["y"], bins=(nx, ny - 1),
                                 range=((xrange[0] - 0.5 * dx,
                                         xrange[1] + 0.5 * dx),
                                        yrange))
        ch = np.concatenate([np.zeros((nx, 1)),
                             np.cumsum(h, axis=1)],
                            axis=1)
        z = ch / ch[..., -1, np.newaxis]
        x, y = np.meshgrid(0.5 * (x[1:] + x[:-1]), y, indexing="ij")
        levels = np.linspace(-2.0, 2.0, 5)
        levels = 0.5 + 0.5 * scipy.special.erf(2.0 ** -0.5 * levels)
        ax.axhline(-1.0, linestyle="--", color="white", linewidth=0.5)
        ax.axhline(1.0, linestyle="--", color="white", linewidth=0.5)
        ax.contour(x, y, z,
                   levels=levels,
                   colors="white",
                   alpha=0.3)
        cs = ax.contourf(x, y, z,
                         levels=np.linspace(0.0, 1.0, 300),
                         # note: translucent cmaps tend to cause artifacts
                         cmap=CMAP_FOLDED_VIRIDIS,
                         linestyle=":")
        for c in cs.collections: # http://stackoverflow.com/a/32911283
            c.set_edgecolor("face")
        fig.colorbar(cs)
        ax.set_title(title)
        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)
        ax.set_xlim(xlim)
        ax.set_ylim(ylim)

    elif plot_type == "scatter":

        cmap = utils.CMAP_RAINBOW
        for i, (bin, g) in enumerate(sorted(d.groupby(color_bin_cols))):
            color = cmap(float(i) / max_bins)
            ax.plot(g["x"], g["y"], ".",
                    label=str(bin),
                    color=color,
                    markersize=10,
                    markeredgewidth=0,
                    alpha=0.5,
                    picker=2)
        ax.legend()

    fn = f"fit-predictiveness-{plot_type}-{fit_count}-{stat}-{hf}"
    fig.tight_layout()
    utils.savefig(fig, fn)