Обновить цвет Poly3DCollection в l oop в Matplotlib - PullRequest
0 голосов
/ 13 июля 2020

Я хотел бы как можно эффективнее обновить цвет patchcollection = Poly3DCollection(patches,facecolor = colors) в al oop. В моем примере patches содержит много элементов, и я думаю, что мог бы сэкономить время, избегая вызова Poly3DCollection на каждой итерации. Вот MWE желаемого результата, реализованного неэффективным способом:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np 


def point():
    return tuple(np.random.rand(3))

n = 4                   # <-------- This is usually >1000
patches = []
for _ in range(n):
    thispatch = [point() for i in range(5)]
    patches.append(thispatch)  

def myplot1(patches,colors):
    fig = plt.figure(figsize=plt.figaspect(1)*0.7,constrained_layout=False) 
    ax = fig.gca(projection='3d')
    patchcollection = Poly3DCollection(patches,linewidth=0.1,edgecolor="k",facecolor = colors,rasterized=True)
    ax.add_collection3d(patchcollection)
    plt.show()

for _ in range(2):   # <------- This is usually >100
    colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]  # MWE colors  
    myplot1(patches,colors)

Затем я просто хотел проверить, могу ли я передать Poly3DCollection вместо patches. Это работает, но пока не экономит время.

def myplot2(patchcollection,colors):
    fig = plt.figure(figsize=plt.figaspect(1)*0.7,constrained_layout=False) 
    ax = fig.gca(projection='3d')
    ax.add_collection3d(patchcollection)
    plt.show()


for _ in range(2):
    colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]   
    patchcollection = Poly3DCollection(patches,linewidth=0.1,edgecolor="k",facecolor = colors,rasterized=True)
    myplot2(patchcollection,colors)

Однако перемещение Poly3DCollection из l oop приводит к ошибке после первой итерации.

colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]   
patchcollection = Poly3DCollection(patches,linewidth=0.1,edgecolor="k",facecolor = colors,rasterized=True)

for _ in range(2):
    myplot2(patchcollection,colors)

Ошибка:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-7-3df3a5c9df6b> in <module>
      3 
      4 for _ in range(2):
----> 5     myplot2(patchcollection,colors)
      6 

<ipython-input-5-37a10e307ad3> in myplot2(patchcollection, colors)
      2     fig = plt.figure(figsize=plt.figaspect(1)*0.7,constrained_layout=False)
      3     ax = fig.gca(projection='3d')
----> 4     ax.add_collection3d(patchcollection)
      5     plt.show()

~/Software/anaconda3/lib/python3.7/site-packages/mpl_toolkits/mplot3d/axes3d.py in add_collection3d(self, col, zs, zdir)
   2182             col.set_sort_zpos(zsortval)
   2183 
-> 2184         super().add_collection(col)
   2185 
   2186     def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True,

~/Software/anaconda3/lib/python3.7/site-packages/matplotlib/axes/_base.py in add_collection(self, collection, autolim)
   1810         self.collections.append(collection)
   1811         collection._remove_method = self.collections.remove
-> 1812         self._set_artist_props(collection)
   1813 
   1814         if collection.get_clip_path() is None:

~/Software/anaconda3/lib/python3.7/site-packages/matplotlib/axes/_base.py in _set_artist_props(self, a)
    903     def _set_artist_props(self, a):
    904         """set the boilerplate props for artists added to axes"""
--> 905         a.set_figure(self.figure)
    906         if not a.is_transform_set():
    907             a.set_transform(self.transData)

~/Software/anaconda3/lib/python3.7/site-packages/matplotlib/artist.py in set_figure(self, fig)
    710         # to more than one Axes
    711         if self.figure is not None:
--> 712             raise RuntimeError("Can not put single artist in "
    713                                "more than one figure")
    714         self.figure = fig

RuntimeError: Can not put single artist in more than one figure

Мой желаемый результат без ошибок сделает следующее:

colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]   
patchcollection = Poly3DCollection(patches,linewidth=0.1,edgecolor="k",facecolor = colors,rasterized=True)

for _ in range(2):
    myplot2(patchcollection,colors)
    colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]   
    patchcollection.updatecolor(colors) # I'm looking for update function here

1 Ответ

1 голос
/ 17 июля 2020

Минимальный пример изменения цвета - это повторное использование одного и того же рисунка и обновление. Я использовал интерактивный режим (plt.ion) с паузой, чтобы разрешить перерисовку, и при желании вы можете добавить ввод для блокировки ожидания пользователя.

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np 


def point():
    return tuple(np.random.rand(3))

n = 4                   # <-------- This is usually >1000
patches = []
for _ in range(n):
    thispatch = [point() for i in range(5)]
    patches.append(thispatch)  

fig = plt.figure(figsize=plt.figaspect(1)*0.7,constrained_layout=False) 
ax = fig.gca(projection='3d')
colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]  # MWE colors  
patchcollection = Poly3DCollection(patches,linewidth=0.1,edgecolor="k",facecolor = colors,rasterized=True)
ax.add_collection3d(patchcollection)
plt.ion()
plt.show()
for i in range(10):
    print(i)
    colors = ["tab:blue" if np.random.rand()<0.5 else "tab:orange" for patch in patches]  # MWE colors  
    patchcollection.set_color(colors)
    #input("Press Enter to redraw")
    plt.pause(0.01)

Ошибка, которую вы получили, в основном потому, что вы воссоздали все каждая цифра l oop, что всегда будет намного медленнее. Кроме того, не уверен, возможно ли / актуально, но проверьте blitting в matplotlib.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...