示例#1
0
def draw_energy_autocorr(dataset, axis=None):
    if axis is None:
        fig, new_axis = plt.subplots()
    else:
        new_axis = axis
    tsteps = dataset["tsteps"]
    en = dataset["energy"].values
    en_k = np.fft.fft(en, axis=-1)
    en_corr = np.fft.ifft((en_k * en_k.conj()), axis=-1).real
    corr_ds = xr.DataArray(en_corr,
                           coords=dataset["energy"].coords,
                           attrs=dataset["energy"].attrs)
    # TODO: StackOverflow - ? easier way to cast fft over dataset.
    mean, stdev = gu.mean_std(corr_ds, dim=['run'])
    # TODO: add fitting+plotting code to determine+display correlation time
    if len(np.shape(mean)) != 1:
        print("WARNING: draw_energy encountered unexpected dimensions"
              " after averaging over runs.")
    # new_axis.plot(np.log10(tsteps.values), np.log10(mean.values))
    new_axis.errorbar(
        tsteps.values,
        mean.values,  # yerr=stdev.values,
        capsize=2.)
    if axis is None:
        return (fig, new_axis)
    else:
        return axis
示例#2
0
def draw_bend_autocorr_rw(dataset, dims=2):
    count = dataset["tsteps"].size
    tmp = 100
    display_counts = []
    while tmp <= count:
        display_counts.append(tmp)
        tmp = int(tmp * np.sqrt(10000))
    x, y = naive_curve(dataset, dims)
    fig, axes = plt.subplots(ncols=len(display_counts),
                             sharey='row',
                             squeeze=False)
    for ax, count in zip(axes[0], display_counts):
        tmp = (dataset["bend_autocorr"].isel(run=0,
                                             kickSize=0,
                                             tsteps=slice(count)))
        tmp_mean, tmp_std = gu.mean_std(tmp, dim='tsteps')
        ax.errorbar(x,
                    tmp_mean.values,
                    yerr=tmp_std.values,
                    capsize=2.0,
                    label="RW",
                    color="red")
        ax.plot(x, y, label="Naive", color="green")
        ax.set_title("avg over {0} RWs".format(count))
        ax.legend(loc="lower right")
    fig.suptitle(
        "#rods={0}, Correlation function averaged over random walks.".format(
            dataset.attrs["rodCount"]))
    plt.show(block=False)
    return (fig, axes)
示例#3
0
def draw_angle_profile(dataset, axis=None, total_only=False, show=None):
    def tsteps_slice(ndraw):
        nonlocal dataset
        n = len(dataset["tsteps"])
        if ndraw > n:
            ndraw = n
            print("WARNING: attempting to draw at more points than sampled.")
        return dataset["tsteps"][::n // ndraw]

    if axis is None:
        fig, new_axis = plt.subplots()
    else:
        new_axis = axis

    if show is None:
        ndraw = 5
        tsteps = tsteps_slice(ndraw)
    elif isinstance(show, int):
        ndraw = show
        tsteps = tsteps_slice(ndraw)
    elif show == "all":
        tsteps = dataset["tsteps"]
    else:
        raise ValueError(
            "show should be one of None, int (> 0) or the string 'all'.")

    mean, stdev = gu.mean_std(dataset["angles"].sel(tsteps=tsteps) /
                              (2 * np.pi),
                              dim=['run'])
    if len(np.shape(
            mean)) != 3:  # one for time, one for rods, one for 3 angles
        print("WARNING: draw_angle_profile encountered unexpected dimensions"
              " after averaging over runs.")
    x = np.arange(dataset.attrs["rodCount"])
    # if not total_only:
    #     for (i, a) in enumerate(ANGLES_STR):
    #         new_axis.errorbar(x, mean.isel(angle_str=i),
    #                           yerr=stdev.isel(angle_str=i), label=a)
    # TODO: replace phi + psi (as a proxy) with actual twist value
    # ? How to compute total twist from phi, theta, psi values
    for tstep in tsteps:
        tmp_mean, tmp_std = mean.sel(tsteps=tstep), stdev.sel(tsteps=tstep)
        new_axis.plot(
            x,
            tmp_mean.isel(angle_str=0) + tmp_mean.isel(angle_str=2),
            # yerr=(tmp_std.isel(angle_str=0)**2 + tmp_std.isel(angle_str=2)**2)**0.5,
            label=("t = " + str(tstep.values)))
    new_axis.legend(loc="upper left")
    new_axis.set_ylabel("Angle/2π radians")
    new_axis.set_xlabel("Rod number")
    if axis is None:
        return (fig, new_axis)
    else:
        return axis
示例#4
0
def draw_energy(dataset, axis=None, show=None):
    flag = axis is None
    if flag:
        fig, axis = plt.subplots()
    # else:
    #     new_axis = axis
    tsteps = dataset["tsteps"]
    mean, stdev = gu.mean_std(dataset["energy"].sel(tsteps=tsteps),
                              dim=['run'])
    if len(np.shape(mean)) != 1:
        print("WARNING: draw_energy encountered unexpected dimensions"
              " after averaging over runs.")
    axis.errorbar(tsteps.values, mean.values, yerr=stdev.values, capsize=2.)
    if flag:
        return (fig, axis)
    return axis
示例#5
0
def draw_acceptance(dataset, axis=None):
    if axis is None:
        fig, new_axis = plt.subplots()
    else:
        new_axis = axis
    for (i, a) in enumerate(ANGLES_STR):
        mean, stdev = gu.mean_std(dataset["acceptance"].isel(angle_str=i),
                                  dim=["run"])
        new_axis.errorbar(dataset["tsteps"].values,
                          mean.values,
                          yerr=stdev.values,
                          label=a)
    new_axis.legend(loc="upper right")
    new_axis.set_xlabel("Time (Monte Carlo steps)")
    new_axis.set_ylabel("Acceptance probability")
    if axis is None:
        return (fig, new_axis)
    else:
        return axis
示例#6
0
def hat_curve(dataset):
    """Draws a curve for z_bead vs turns."""
    twists = dataset["twists"]
    tsteps = dataset["tsteps"]
    tslice = slice(0, tsteps.size, tsteps.size // twists.size)
    z_mean, z_stdev = gu.mean_std(
        dataset["extension"].isel(tsteps=tslice).sel(axis='z'), dim='run')

    def f(x):
        tmp = x.rename({"tsteps": "twists"})
        tmp["twists"] = twists
        return tmp

    z_mean = f(z_mean).to_dataset().rename({"extension": "mean"})
    z_stdev = f(z_stdev).to_dataset().rename({"extension": "stdev"})

    z = xr.merge([z_mean, z_stdev])
    fig, axis = plt.subplots()
    axis.errorbar(z["twists"].values / (2 * np.pi),
                  z["mean"].values,
                  yerr=z["stdev"].values,
                  label='z')
    plt.legend(loc='upper left')
    plt.show(block=False)
示例#7
0
def draw_bend_autocorr(dataset, energy=False, rw_dataset=None, dims=2):
    fig, axes = plt.subplots(nrows=2 if energy else 1,
                             ncols=min(5, len(dataset["run"])),
                             sharey='row',
                             squeeze=False)
    x, y = naive_curve(dataset, dims)
    if rw_dataset is not None:
        total_num_rw = rw_dataset["tsteps"].size
        x2 = rw_dataset.attrs["rodLength"] * np.arange(
            rw_dataset.attrs["rodCount"])
        y2 = (rw_dataset["bend_autocorr"].isel(run=0,
                                               kickSize=0).mean(dim='tsteps'))
        test_num_rw = 25

        def partial_rw_y(start):
            return (rw_dataset["bend_autocorr"].isel(
                run=0, kickSize=0,
                tsteps=slice(start, start + test_num_rw)).mean(dim='tsteps'))

        ys = [partial_rw_y(yi) for yi in [0, 50, 100, 250, 500, 750]]
    start = max(500, int(dataset["tsteps"][0]))
    step = int(dataset["tsteps"][1] - dataset["tsteps"][0])
    stop = int(dataset["tsteps"][-1] + step)
    for (i, ax) in enumerate(axes[0]):
        for ks in dataset["kickSize"]:
            tmp = (dataset["bend_autocorr"].sel(run=i,
                                                kickSize=ks,
                                                tsteps=np.arange(
                                                    start, stop, step)))
            tmp_mean, tmp_std = gu.mean_std(tmp, dim='tsteps')
            ax.errorbar(
                x,
                tmp_mean.values,  # yerr=tmp_std.values,
                capsize=2.0,
                label="MC, ks={0}".format(ks.values),
                color='blue')
            # ax.set_yscale('log')
        if rw_dataset is not None:
            ax.plot(x2, y2, color='red', label="{0} RW".format(total_num_rw))
            for yi in ys:
                ax.plot(x2,
                        yi,
                        color='grey',
                        label="{0} RW".format(test_num_rw))
            ax.plot(x, y, color='green', label="Naive")
        else:
            ax.plot(x, y, color='green', label="Naive")
        ax.set_ylim(0, 1)
        ax.set_title("Run# = {0}".format(i))

    handles, labels = axes[0][-1].get_legend_handles_labels()
    by_label = OrderedDict(zip(labels, handles))
    axes[0][-1].legend(by_label.values(), by_label.keys(), loc="upper right")

    axes[0][0].set_ylabel("(Tangent vector autocorrelation)")
    axes[0][len(axes[0]) // 2].set_xlabel("Length (nm)")
    if energy:
        for (i, ax) in enumerate(axes[1]):
            for ks in dataset["kickSize"]:
                draw_energy_autocorr(
                    dataset.sel(kickSize=ks).isel(run=slice(i, i + 1)),
                    axis=ax)
        axes[1][0].set_ylabel("Energy autocorrelation")
        axes[1][len(axes[1]) // 2].set_xlabel("Time")
    fig.suptitle(
        "#rods={1}, Correlation function averaged over t={2} to t={0} in steps of {3}"
        .format(int(dataset["tsteps"][-1]), dataset.attrs["rodCount"], start,
                step))
    plt.show(block=False)
    return (fig, axes)
示例#8
0
def draw_force_extension(dataset, acceptance=True):
    kickSizes = dataset.coords["kickSize"].values
    forces = dataset.coords["force"].values
    runs = dataset.coords["run"].values
    B = dataset.attrs["B"]
    L = dataset.attrs["rodCount"]
    T = dataset.attrs["temperature"]
    Pinv = dataset.data_vars["Pinv"].values
    pre_steps = dataset.attrs["pre_steps"]
    extra_steps = dataset.attrs["extra_steps"]

    fig, axes = plt.subplots(nrows=(2 if acceptance else 1),
                             ncols=kickSizes.size,
                             sharex="row",
                             sharey="row",
                             squeeze=False)
    sns.set_style("darkgrid")
    ms_curve_x, ms_curve_y = marko_siggia_curve(B, 740)

    for (j, ks) in enumerate(kickSizes):
        # 'axis' dimension is the last dimension
        # there doesn't seem to be a simple way to broadcast np.linalg.norm
        tmp = gu.norm(dataset["extension"].sel(kickSize=ks), dim='axis')
        mean, stdev = gu.mean_std(tmp.groupby("force"))
        print(mean.values)
        print(forces)
        axes[0, j].errorbar(mean.values,
                            forces,
                            xerr=stdev.values,
                            capsize=4.0,
                            linestyle='')
        axes[0, j].plot(ms_curve_x, ms_curve_y)
        axes[0, j].set_xlim(left=500, right=740)
        axes[0, j].set_ylim(bottom=-0.5, top=10 + 0.5)
        axes[0, j].set_title("kick size = {0}".format(ks))
        axes[0, j].set_xlabel("")
        axes[0, j].set_ylabel("")
    axes[0, 0].set_ylabel("Force (pN)")
    axes[0, kickSizes.size // 2].set_xlabel("Extension (nm)")

    # Molecular dynamics simulation will not have acceptance values.
    acceptance = acceptance and ("acceptance" in dataset)
    if acceptance:
        for (j, ks) in enumerate(kickSizes):
            tmp = dataset["acceptance"].sel(kickSize=ks)
            for (j_a, angle) in enumerate(ANGLES_STR):
                mean, stdev = gu.mean_std(
                    tmp.isel(angle_str=j_a).groupby("force"))
                axes[1, j].errorbar(forces,
                                    mean.values,
                                    yerr=stdev.values,
                                    label=angle)
                axes[1, j].set_ylim(bottom=0, top=1)
            axes[1, 0].set_ylabel("Acceptance ratio")
            axes[1, kickSizes.size // 2].set_xlabel("Force (pN)")

    fig.suptitle(
        ("Contour length (straight) L_0 = 740 nm, #rods = {6}, T = {7:.0f} K\n"
         "Effective persistence length Lp = {5:.1f} nm, "
         "Intrinsic disorder persistence length P = {0:.1f} nm\n"
         "Thermalization steps = {1}, extra steps = {2}, "
         "#samples in extra steps = {3}, runs = {4}").format(
             1 / Pinv if Pinv != 0 else np.inf, pre_steps, extra_steps,
             dataset.coords["tsteps"].size, runs, B, L, T),
        fontdict={"fontsize": 10})
    plt.legend(loc="upper right")
    plt.show(block=False)