Tkinter和子图行为中的内存溢出

时间:2017-06-17 00:45:40

标签: python image matplotlib tkinter

我正在尝试制作6个饼图,每个饼图都嵌入了图像。我已经能够生成饼图和子图(空)。但是,我不了解在右下角生成所有图表的行为。 (它目前正在做)。另外,当我运行6个图表时,我收到内存错误。 (当我运行两个图表时不会发生这种情况)

Tkinter回调中的异常:

  

的MemoryError

我包含了我的代码,有足够的数据线来生成两个图表。可以使用绘图和保存实体块png文件轻松构建5个丢失的png文件。

我也意识到这里有两个问题,但由于它们都来自相同的代码,我正在询问这两个问题。

所以 1)如何让子图将饼图分布在自己的位置。 In Matplotlib, what does the argument mean in fig.add_subplot(111)?似乎也没有帮助我。

2)我怎样才能避免记忆错误(我可能已经开了一些东西而且不知道如何关闭它,但我不知道这个Tkinter and pyplot running out of memory出现了什么或怎么样有类似的问题,但我无法理解它是如何修复的

import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import sys
import scipy.stats

#import panda as pd
import numpy as np

size_distribution = np.array([
    [ 1 , 1 , 0.48 , 0.42 , 0.10 ],
    [ 1 , 1 , 0.52 , 0.38 , 0.10 ],
    [ 2 , 2 , 0.38 , 0.42 , 0.20 ],
    [ 2 , 2 , 0.42 , 0.38 , 0.20 ]])

def name_of_files(): # files named as such in directory with python script
    Variety = np.array(['_A_', '_B_']) #Variety of tested stuff
    Treatment = np.array(['_1_', '_2_', '_3_']) # Treatment of stuff
    Cut = np.array(['_i_', '_ii_']) # Cut of stuff
    return Variety, Treatment, Cut

def label(): # provides info on labelling in pie chart
    var = np.array(['A_', 'B_'])
    treat = np.array(['1_', '2_', '3_'])
    return var, treat

def size(xx, strt, end): #produces individual pie chart with plt.show() or sends wedges to main
    Variety, Treatment, Cut = name_of_files()
    var, treat = label()
    long = int(len(size_distribution))
    count = int(strt)
    cut = int(0)
    while count < (long - 1) and count < end:
        coarse = np.mean([xx[count][2], xx[count+1][2]])
        fine = np.mean([xx[count][3], xx[count+1][3]])
        residue = np.mean([xx[count][4], xx[count+1][4]])
        name = (str(Variety[int(xx[count][0])-1]) +
                str(Treatment[int(xx[count][1])-1]) +
                str(Cut[int(cut)]) +
                '.png')
        #print(name, cut)
        if cut == 0:
            name_coarse = name
            label_coarse = (str(var[int(xx[count][0])-1]) + '\n' +
                            str(treat[int(xx[count][1])-1]) + '\n' +
                            'coarse fraction:\n' + str(np.around(coarse, 3)*100) + '%')
            #print(label_coarse, coarse)
            cut = int(1)
        elif cut == 1:
            name_fine = name
            label_fine = (str(var[int(xx[count][0])-1]) + '\n' +
                            str(treat[int(xx[count][1])-1]) + '\n' +
                            'fine fraction:\n' + str(np.around(fine, 3)*100) + '%')
            label_residue = ('\n\n' + str(var[int(xx[count][0])-1]) + ', ' +
                            str(treat[int(xx[count][1])-1]) + '\n' +
                            'residue fraction: ' + str(np.around(residue, 3)*100) + '%')
            #print(label_fine, fine)
            #print(label_residue, residue)
            #print('\t\t\t\t', fine+coarse+residue)
            cut = int(0)
            #print('\n\n\t\t\tcount = ', count)
            count += 2
            #print('\n\n\t\t\tcount = ', count)


            file_index = np.array([name_coarse, 'Black.png', name_fine])
            labels = np.array([label_coarse, label_residue, label_fine])
            total = [coarse, residue, fine]
            plt.gca().axis('equal')
            wedges, texts = plt.pie(total, startangle=90, labels=labels,
                        wedgeprops = { 'linewidth': 3, "edgecolor" :"k",
                                       "fill":False,  })
            positions = [(-1,0.3),(0,-0.5),(0.5,0.5)]
            zooms = [0.4,0.4,0.4]
            for i in range(3):
                #print('\ti = ', i)
                fn = str(file_index[i]).format(labels[i].lower(), fontsize=20)
                img_to_pie(fn, wedges[i], xy=positions[i], zoom=zooms[i] )
                wedges[i].set_zorder(10)
            #plt.show() #shows the pie chart nicely
            #plt.close('all')
            #print('Wedges type: ',type(wedges),'\nLength: ', len(wedges))
            #print('Texts type: ',type(wedges),'\nTexts: ', len(wedges))
            #print(type(texts), len(texts))
            #print(locals())
    return wedges

def img_to_pie( fn, wedge, xy, zoom=1, ax = None):
    if ax==None: ax=plt.gca()
    im = plt.imread(fn, format='png')
    path = wedge.get_path()
    patch = PathPatch(path, facecolor='none')
    plt.gca().add_patch(patch)
    imagebox = OffsetImage(im, zoom=zoom, clip_path=patch, zorder=-10)
    ab = AnnotationBbox(imagebox, xy, xycoords='data', pad=0, frameon=False)
    ax.add_artist(ab)
    return ()

def main():
    fig = plt.figure()
    ho = fig.add_subplot(1, 2, 1)
    hm = fig.add_subplot(1, 2, 2)
    '''
    f, ((ho , hm, hs), (mo, mm, ms)) = (
        plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True,
                 squeeze=False, subplot_kw=None, gridspec_kw=None))
    #plt.show() # six empty plots as expected'''
    j = [ho, hm]#, hs]#, mo, mm, ms]
    x = [0, 2]#, 4]#, 6, 8, 10]
    count = 0
    int(count)
    while count < len(x):
        j[count] = size(size_distribution, x[count], x[count]+2)
        print(x[count], '\n', j[count])
        count += 1
    print(ho, '\n', hm)
    plt.show()  

main()

1 个答案:

答案 0 :(得分:1)

首先,我在回答this question时为你写的函数接受了一个参数ax,你应该用它来设置你想要绘制的轴。

此外,您需要将饼图绘制到要显示它的轴ax,即使用ax.pie(..)而不是plt.pie(..)

您可以使用

创建子图
f, ax_arr = plt.subplots(nrows=2, ncols=3)

other recent question的答案,并将ax_arr内的轴提供给size函数,然后您需要像size(xx, strt, end, ax)一样编写。

以下代码

import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import scipy.stats
import numpy as np

size_distribution = np.array([
    [ 1 , 1 , 0.48 , 0.42 , 0.10 ],
    [ 1 , 1 , 0.52 , 0.38 , 0.10 ],
    [ 2 , 2 , 0.38 , 0.42 , 0.20 ],
    [ 2 , 2 , 0.42 , 0.38 , 0.20 ]])

def name_of_files(): # files named as such in directory with python script
    Variety = np.array(['_A_', '_B_']) #Variety of tested stuff
    Treatment = np.array(['_1_', '_2_', '_3_']) # Treatment of stuff
    Cut = np.array(['_i_', '_ii_']) # Cut of stuff
    return Variety, Treatment, Cut

def label(): # provides info on labelling in pie chart
    var = np.array(['A_', 'B_'])
    treat = np.array(['1_', '2_', '3_'])
    return var, treat

filenames=["data/blueberries.png", "data/blackberries.png","data/raspberries.png"]

def size(xx, strt, end, ax=None): #produces individual pie chart with plt.show() or sends wedges to main
    if not ax: ax=plt.gca()
    Variety, Treatment, Cut = name_of_files()
    var, treat = label()
    long = int(len(size_distribution))
    count = int(strt)
    cut = int(0)
    while count < (long - 1) and count < end:
        coarse = np.mean([xx[count][2], xx[count+1][2]])
        fine = np.mean([xx[count][3], xx[count+1][3]])
        residue = np.mean([xx[count][4], xx[count+1][4]])
        name = (str(Variety[int(xx[count][0])-1]) +
                str(Treatment[int(xx[count][1])-1]) +
                str(Cut[int(cut)]) +
                '.png')

        if cut == 0:
            name_coarse = name
            label_coarse = (str(var[int(xx[count][0])-1]) + '\n' +
                            str(treat[int(xx[count][1])-1]) + '\n' +
                            'coarse fraction:\n' + str(np.around(coarse, 3)*100) + '%')

            cut = int(1)
        elif cut == 1:
            name_fine = name
            label_fine = (str(var[int(xx[count][0])-1]) + '\n' +
                            str(treat[int(xx[count][1])-1]) + '\n' +
                            'fine fraction:\n' + str(np.around(fine, 3)*100) + '%')
            label_residue = ('\n\n' + str(var[int(xx[count][0])-1]) + ', ' +
                            str(treat[int(xx[count][1])-1]) + '\n' +
                            'residue fraction: ' + str(np.around(residue, 3)*100) + '%')
            cut = int(0)
            count += 2

            file_index = np.array([name_coarse, 'Black.png', name_fine])
            labels = np.array([label_coarse, label_residue, label_fine])
            total = [coarse, residue, fine]
            ax.axis('equal')
            wedges, texts = ax.pie(total, startangle=90, labels=labels,
                        wedgeprops = { 'linewidth': 3, "edgecolor" :"k",
                                       "fill":False,  })
            positions = [(-1,0.3),(0,-0.5),(0.5,0.5)]
            zooms = [0.4,0.4,0.4]
            for i in range(3):

                #fn = str(file_index[i]).format(labels[i].lower(), fontsize=20)
                fn = filenames[i]
                img_to_pie(fn, wedges[i], xy=positions[i], zoom=zooms[i],ax=ax )
                wedges[i].set_zorder(10)

    return wedges

def img_to_pie( fn, wedge, xy, zoom=1, ax = None):
    if ax==None: ax=plt.gca()
    im = plt.imread(fn, format='png')
    path = wedge.get_path()
    patch = PathPatch(path, facecolor='none')
    ax.add_patch(patch)
    imagebox = OffsetImage(im, zoom=zoom, clip_path=patch, zorder=10)
    ab = AnnotationBbox(imagebox, xy, xycoords='data', pad=0, frameon=False)
    ax.add_artist(ab)
    return ()

def main():

    f, ax_arr = plt.subplots(nrows=2, ncols=3)

    x = [0, 2, 4, 6, 8, 10] 
    count = 0
    for i, ax in zip(x, ax_arr.flatten()):
        wedges = size(size_distribution, x[count], x[count]+2, ax=ax)

    plt.show()  

main()

然后产生这个情节

enter image description here

我不关心看标签,因为这部分代码很乱(下次请问请创建一个没有多余标签的最小例子)。

你得到的错误可能来自我注释掉的那一行,这没有用:

#fn = str(file_index[i]).format(labels[i].lower(), fontsize=20)

因为str没有fontsize参数。