Есть ли способ пометить несколько трехмерных поверхностей в matplotlib? - PullRequest
2 голосов
/ 05 апреля 2019

Я пытаюсь решить задачу нелинейной математической оптимизации с линейными ограничениями.Для этого я пытаюсь визуализировать ограничения в 3d, чтобы увидеть, что происходит и почему я получаю реальные решения для некоторых параметров в ограничениях, а не для других.

Чтобы добиться этого, я хочуиспользуйте matplotlib из python для генерации трехмерных поверхностей (плоскостей, поскольку все мои ограничения линейны).

Однако без маркировки на чертеже очень трудно определить, какая поверхность принадлежит какому-либо ограничению,Это заставило меня захотеть найти способ добавить легенду с цветами внутри графика.

Я понимаю, что уже есть способ сделать это в 2D, внутри метода ax.plot() или ax.scatter(), но попытка сделать то же самое не работала с ax.plot_surface(X, Y, Z, label = 'mylabel')

Полный сценарий приведен ниже:


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


fig = plt.figure()
ax = plt.axes(projection='3d')

plt.rcParams['legend.fontsize'] = 10


# First constraint
g2 = np.linspace(-5,5,2)
g3 = np.linspace(-5,5,2)
G2,G3 = np.meshgrid(g2,g3)
G4_1 = -1.18301270189222 - 0.5*G2 + 0.5*G3
ax = fig.gca(projection='3d')
c1 = ax.plot_surface(G2, G3, G4_1, label = "c1")

# Second
G3, G4 = np.meshgrid(g2, g3)
G2 = G3
c2 = ax.plot_surface(G2, G3, G4, label = "c2")

# Third
G2,G3 = np.meshgrid(g2,g3)
G4 = (0.408248290463863*G2 + 0.408248290463863*G3 -0.707106781186548)/1.63299316185545
c3 = ax.plot_surface(G2, G3, G4, label = "c3")

# And forth
G4 = (1.04903810567666 - (0.288675134594813*G2 + 0.288675134594813*G3))/0.577350269189626
c4 = ax.plot_surface(G2, G3, G4, label="c4")



ax.legend() # -> error : 'AttributeError: 'Poly3DCollection' object has no attribute '_edgecolors2d''


# labeling the figure
fig.suptitle("Constraints")
#plt.xlabel('g2', fontsize=14)
#plt.ylabel('g3', fontsize=14)
ax.set_xlabel(r'$g_2$', fontsize=15, rotation=60)
ax.set_ylabel('$g_3$', fontsize=15, rotation=60)
ax.set_zlabel('$g_4$', fontsize=15, rotation=60)
plt.savefig('Constraints.jpg')
plt.show()

Что приводит к следующему рисунку.

plot

Как вы, наверное, уже видели, нет никакого способа определить, какой поверхности принадлежит какое ограничение, и чего я хочу достичь, это легенда, например, здесь .

Я прочитал ответ на этот вопрос , но он не сработал, поскольку у меня несколько поверхностей.После попытки показывается только один ярлык, а не четыре.

Так что мой вопрос, есть ли способ добавить легенду к моему ax.plot_surface или любому другому подходящему хаку?

1 Ответ

2 голосов
/ 05 апреля 2019

Вот, пожалуйста.

Решение этой ошибки было здесь: ax.legend() # -> error : 'AttributeError: 'Poly3DCollection' object has no attribute '_edgecolors2d''.
Я считаю, что это ошибка.

Если вы исследуете какие-либо из ваших поверхностных объектов (пустьскажем c1) вы можете видеть, что у них есть атрибут '_edgecolors3d', который должен вызываться при создании легенды.

Таким образом, мы просто создаем новый атрибут с именем '_edgecolors2d' с тем же содержимым, что и'_edgecolors3d'.

Как только проблема '_edgecolors2d' будет решена, вы столкнетесь с новой с '_facecolors2d'.Мы повторяем ту же процедуру, и все готово.


fig = plt.figure()
ax = plt.axes(projection='3d')

plt.rcParams['legend.fontsize'] = 10


# First constraint
g2 = np.linspace(-5,5,2)
g3 = np.linspace(-5,5,2)
G2,G3 = np.meshgrid(g2,g3)
G4_1 = -1.18301270189222 - 0.5*G2 + 0.5*G3
ax = fig.gca(projection='3d')
c1 = ax.plot_surface(G2, G3, G4_1, label = "c1")
c1._facecolors2d=c1._facecolors3d
c1._edgecolors2d=c1._edgecolors3d

# Second
G3, G4 = np.meshgrid(g2, g3)
G2 = G3
c2 = ax.plot_surface(G2, G3, G4, label = "c2")
c2._facecolors2d=c2._facecolors3d
c2._edgecolors2d=c2._edgecolors3d

# Third
G2,G3 = np.meshgrid(g2,g3)
G4 = (0.408248290463863*G2 + 0.408248290463863*G3 -0.707106781186548)/1.63299316185545
c3 = ax.plot_surface(G2, G3, G4, label = "c3")
c3._facecolors2d=c3._facecolors3d
c3._edgecolors2d=c3._edgecolors3d

# And forth
G4 = (1.04903810567666 - (0.288675134594813*G2 + 0.288675134594813*G3))/0.577350269189626
c4 = ax.plot_surface(G2, G3, G4, label="c4")

c4._facecolors2d=c4._facecolors3d
c4._edgecolors2d=c4._edgecolors3d

ax.legend() # -> error : 'AttributeError: 'Poly3DCollection' object has no attribute '_edgecolors2d''


# labeling the figure
fig.suptitle("Constraints")
#plt.xlabel('g2', fontsize=14)
#plt.ylabel('g3', fontsize=14)
ax.set_xlabel(r'$g_2$', fontsize=15, rotation=60)
ax.set_ylabel('$g_3$', fontsize=15, rotation=60)
ax.set_zlabel('$g_4$', fontsize=15, rotation=60)
plt.savefig('Constraints.jpg')
plt.show()

output

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