如何在不打开两个窗口的情况下将文本框放置在matplotlib图中?

时间:2019-02-07 11:38:22

标签: python matplotlib tkinter

我使用tkinter和matplotlib编写了一个小程序,该程序绘制了正态分布曲线和置信区间。我希望该图使用plt.text()在左上角有一个小文本框,其中包含有关用户输入的一些信息以及后端模型计算出的其他一些相关信息(例如,可靠性,范数等)。

我明确希望避免使用fig, ax = plt.subplots(),因为这将打开两个窗口(其中一个为空,另一个包含绘图)。

但是我意识到我必须创建一个子图才能使用transform=ax.transAxes并确保文本框出现在我的图窗口中(请参见text caption not appearing matplotlib)。没有此关键字参数,我将不得不使用显式的数据坐标,这是我不能做的,因为轴坐标可以根据用户输入而改变。

如何在不打开两个窗口的情况下将文本框放在左上角?

这是我的代码:

import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import numpy as np
import math
from scipy.stats import norm
from scipy.stats import zscore


class Application:
    def __init__(self, master):
        self.master = master
        self.callPlotWindow()

    def callPlotWindow(self):

        plotdata = dict()
        plotdata['reliability'] = 0.94
        plotdata['sd'] = 10
        plotdata['mean'] = 50
        plotdata['normvalue'] = 66
        plotdata['confidence_level'] = '80%'
        plotdata['question'] = 'einseitig'
        plotdata['hypothesis'] = 'Äquivalenzhypothese'
        plotdata['plot_ci'] =  4.12298113505264
        plotdata['plot_ci_lower'] =  63.93850943247368
        plotdata['plot_ci_upper'] = 68.06149056752632

        # turn on interactive mode
        plt.ion()

        # if there is already a plot window clear old plot
        if plt:
            plt.clf()

        # create x values for normal distribution
        x_normdist = np.concatenate((
        np.linspace(plotdata["mean"] - 3 * plotdata["sd"], plotdata["mean"] - 2 * plotdata["sd"],endpoint=False),
        np.linspace(plotdata["mean"] - 2 * plotdata["sd"], plotdata["mean"] - 1 * plotdata["sd"],endpoint=False),
        np.linspace(plotdata["mean"] - 1 * plotdata["sd"], plotdata["mean"] + 1 * plotdata["sd"],endpoint=False),
        np.linspace(plotdata["mean"] + 1 * plotdata["sd"], plotdata["mean"] + 2 * plotdata["sd"],endpoint=False),
        np.linspace(plotdata["mean"] + 2 * plotdata["sd"], plotdata["mean"] + 3 * plotdata["sd"])
        ))

        # plot normal distribution curve
        y_normdist = norm.pdf(x_normdist,plotdata["mean"],plotdata["sd"])
        plt.plot(x_normdist,y_normdist)

        # create logical lists which are used for 'where'-argument in fill-between method
        average = (x_normdist >= (plotdata["mean"] - 1 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] + 1 * plotdata["sd"]))
        above_and_below_average = (x_normdist >= (plotdata["mean"] - 2 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] - 1 * plotdata["sd"])) | (x_normdist >= (plotdata["mean"] + 1 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] + 2 * plotdata["sd"]))
        far_above_and_below_average = (x_normdist >= (plotdata["mean"] - 3 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] - 2 * plotdata["sd"])) | (x_normdist >= (plotdata["mean"] + 2 * plotdata["sd"])) & (x_normdist <= (plotdata["mean"] + 3 * plotdata["sd"]))

        regions = [average,
        above_and_below_average,
        far_above_and_below_average
        ]

        alpha_values = [0.75,0.5,0.25]

        region_labels = [
        "durchschnittlich",
        "unter-/überdurchschnittlich",
        "weit unter-/überdurchschnittlich"
        ]

        # shade regions under curve, use different alpha channel values and labels
        for idx,region in enumerate(regions):
            plt.fill_between(x_normdist, y_normdist,color="C0",alpha=alpha_values[idx],label=region_labels[idx],where=regions[idx])

        # plot confidence interval
        plt.errorbar(x=plotdata["normvalue"],y=0,xerr=plotdata["plot_ci"],fmt=".k",capsize=10)

        # set x and y axis title
        plt.xlabel(xlabel="Normwert")
        plt.ylabel(ylabel=r'$\phi_{\mu\sigma}(\mathcal{X})$')

        textstr = '\n'.join((
        r'$Normwert: %.2f$' % (plotdata["normvalue"], ),
        r'$Reliabilität: %.2f$' % (plotdata["reliability"], ),
        r'$Mittelwert des Normwertes: %.2f$' % (plotdata["mean"], ),
        r'$Standardabweichung des Normwertes: %.2f$' % (plotdata["sd"],),
        r'$Untere KI-Grenze: %.2f$' % (round(plotdata["plot_ci_lower"],2),),
        r'$Obere KI-Grenze: %.2f$' % (round(plotdata["plot_ci_upper"],2),),
        ))

        # these are matplotlib.patch.Patch properties
        props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)

        # create legend
        plt.legend(loc='upper right', prop={'size': 8})

        # place a text box in upper left in axes coords
        plt.text(0.05, 0.95,textstr,fontsize=14,verticalalignment='top',bbox=props)

if __name__ == "__main__":
    root = tk.Tk()
    my_gui = Application(root)
    root.mainloop()

0 个答案:

没有答案