Как эффективно построить большое количество 3D-эллипсоидов с помощью matplotlib (Axes3D)?

В настоящее время я обрабатываю данные о деформации с помощью python и использую matplotlib (v. 1.5.1) для создания различных графических выходных данных для эллипсоидов конечной деформации.

Обработка 1000 параметров эллипсоидов выполняется довольно быстро (я повторно использую некоторый приятный код Python, доступный здесь https://github.com/minillinim/ellipsoid/blob/master/ellipsoid.py), но узкое место в моем рабочем процессе связано со временем, которое требуется для построения множества трехмерных объектов на трехмерном графике. .

Ниже я прикрепил небольшой фрагмент кода Python, который вычисляет и строит набор случайных эллипсоидов. Хотя 'ellipNumber' небольшой, он работает как шарм. Но когда он достигает 100, это занимает гораздо больше времени ... с 1000, держу пари, у вас не хватит терпения ждать.

Я понимаю, что в 2D использование коллекции — это способ повысить производительность: быстро">Как быстро нарисовать много тысяч кругов?

Предполагая, что коллекция действительно подходит, я огляделся в поисках примера и попытался заполнить Poly3DCollection координатами эллипсоида, как они сделали здесь для многоугольников в 3D: Построение трехмерных полигонов в python-matplotlib, но мне не повезло с настройкой вершин на основе двумерных массивов x,y и z.

Буду очень признателен за любые предложения/комментарии о том, как улучшить производительность построения эллипсоидов!

Ваше здоровье

import numpy as np
from numpy import linalg
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib.colors as colors



fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='3d')

# number of ellipsoids 
ellipNumber = 10

#set colour map so each ellipsoid as a unique colour
norm = colors.Normalize(vmin=0, vmax=ellipNumber)
cmap = cm.jet
m = cm.ScalarMappable(norm=norm, cmap=cmap)

#compute each and plot each ellipsoid iteratively
for indx in xrange(ellipNumber):
    # your ellispsoid and center in matrix form
    A = np.array([[np.random.random_sample(),0,0],
                  [0,np.random.random_sample(),0],
                  [0,0,np.random.random_sample()]])
    center = [indx*np.random.random_sample(),indx*np.random.random_sample(),indx*np.random.random_sample()]

    # find the rotation matrix and radii of the axes
    U, s, rotation = linalg.svd(A)
    radii = 1.0/np.sqrt(s) * 0.3 #reduce radii by factor 0.3 

    # calculate cartesian coordinates for the ellipsoid surface
    u = np.linspace(0.0, 2.0 * np.pi, 60)
    v = np.linspace(0.0, np.pi, 60)
    x = radii[0] * np.outer(np.cos(u), np.sin(v))
    y = radii[1] * np.outer(np.sin(u), np.sin(v))
    z = radii[2] * np.outer(np.ones_like(u), np.cos(v))

    for i in range(len(x)):
        for j in range(len(x)):
            [x[i,j],y[i,j],z[i,j]] = np.dot([x[i,j],y[i,j],z[i,j]], rotation) + center


    ax.plot_surface(x, y, z,  rstride=3, cstride=3,  color=m.to_rgba(indx), linewidth=0.1, alpha=1, shade=True)
plt.show()

3D-график с 10 случайными эллипсоидами:

3D-график с 10 случайными эллипсоидами


person Guillaume Duclaux    schedule 31.01.2017    source источник
comment
Внутри каждый plot_surface создает art3d.Poly3DCollection. Таким образом, вы ничего не получаете, делая вручную то, что делается автоматически. Я также думаю, что 100 объектов на самом деле находятся на грани того, что можно понять, глядя на фигуру, так как же может быть мотивирована потребность в 1000 объектах? Может ли быть лучший способ передать ту же информацию?   -  person ImportanceOfBeingErnest    schedule 31.01.2017
comment
У вас есть очень веская точка зрения, и я также создаю ряд карт и диаграмм, чтобы проиллюстрировать изменение моделей деформации в интересующей меня поверхности или объеме. В моей области (геология) мы обычно измеряем конечную деформацию горных пород с помощью некоторых маркеров и представляем величину деформации с помощью эллипсоидов. Так что это определенно один из важных способов иллюстрации пространственного изменения деформации.   -  person Guillaume Duclaux    schedule 31.01.2017
comment
Я работаю с 3D-моделями размером до 1024 ^ 3, и при изучении простого раздела этого тома я получаю эллипсоиды 1024 ^ 2, многие (скажем, 70%) редко напрягаются, и я могу просто их пороговое значение перед построением графика. Обычно я рисую только один на каждые 100 эллипсоидов, но в итоге у меня их около 3000. Метод работает, и я по-прежнему убежден, что он ценен. Здесь я просто прыгал, чтобы улучшить производительность процесса.   -  person Guillaume Duclaux    schedule 31.01.2017
comment
Присмотревшись повнимательнее, вы можете уменьшить количество отрисовываемых точек. На данный момент вы вычисляете 60 х 60 = 3600 точек на эллипс. Я бы предложил использовать только 9 точек на измерение. Для этого может потребоваться установить для stride значение 1 вместо 3, но вы все равно выиграете в 5 раз быстрее.   -  person ImportanceOfBeingErnest    schedule 31.01.2017
comment
Уменьшение количества точек на эллипсоид дает значительное улучшение времени построения. С шагом 1 результирующий объект достаточно гладкий для моего приложения. Спасибо за предложения!   -  person Guillaume Duclaux    schedule 01.02.2017
comment
Более легким решением было бы построить собственные векторы, масштабированные по их величине.   -  person Seph42    schedule 06.05.2020