Python matplotlib - форматирование с сеткой для пользовательской функции - PullRequest
1 голос
/ 27 марта 2012

У меня есть функция funcPower3, тело которой представлено ниже.Я хотел бы построить эту функцию с помощью функций 3D-печати в MatplotLib.Я видел пример на документах scipy с сеткой.Однако в этом примере функция - это не определенная функция, а простая математическая операция:

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,
    linewidth=0, antialiased=False)

В этом примере я черпаю вдохновение, но моя собственная сигнатура функции не совместима с данными из сетки.У меня есть эта ошибка:

 ValueError: zero-size array to minimum.reduce without identity

Код моей функции здесь:

def funcPower3(PARAM):
    inputX1 = open("power3X.txt","r")
    inputY = open("power3Y.txt","r")
    X1=[]
    Y=[]
    for line in inputX1:
        X1.append(float(line))
    for line in inputY:
        Y.append(float(line))
    resTmp_ = 0
    res = 0
    for i in range(len(X1)):
        resTmp_ = Y[i] - (PARAM[0]*(X1[i])**float(PARAM[1]))
        res += resTmp_**2
    return res

И код для построения 3d этой функции здесь:

xmin = 0 ymin =0 xmax = 10 ymax = 1

fig = plt.figure('Power 3')
ax = fig.gca(projection='3d')
Z = []
Xpl = numpy.arange(xmin, xmax, 0.1).tolist()
Ypl = numpy.arange(ymin, ymax, 0.01).tolist()
Xpl, Ypl = numpy.meshgrid(Xpl, Ypl)
Z=[]
for i in range(len(Xpl[0])):
   for j in range(len(Xpl)):
        Z.append(funcPower3([Xpl[j][i],Ypl[j][i]]))
surf=ax.plot_surface(Xpl, Ypl, Z, rstride=8, cstride=8, alpha=0.3,cmap=cm.jet)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
plt.show()

Спасибо за любые советы;))

1 Ответ

4 голосов
/ 28 марта 2012

Цитирование из plot_surface документации :

X, Y, Z: значения данных в виде двумерных массивов

Но ваш Z одномерный. Вам необходимо изменить его, чтобы он соответствовал значениям X и Y. Это должно работать:

Xpl = numpy.arange(xmin, xmax, 0.1).tolist()
Ypl = numpy.arange(ymin, ymax, 0.01).tolist()
Xpl, Ypl = numpy.meshgrid(Xpl, Ypl)

Z=[]
for j in range(len(Xpl)):
   for i in range(len(Xpl[0])):
        # your loop order was backwards
        Z.append(funcPower3([Xpl[j][i],Ypl[j][i]]))

# reshape Z
Z = numpy.array(Z).reshape(Xpl.shape)

fig = plt.figure('Power 3')
ax = fig.gca(projection='3d')
surf=ax.plot_surface(Xpl, Ypl, Z, rstride=8, cstride=8, alpha=0.3,cmap=cm.jet)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
plt.show()

Но у вашего кода есть пара недостатков. Прежде всего, глядя на вашу функцию funcPower3, вы читаете два файла снова и снова для каждого вызова функции. Это слишком расточительно. Вместо этого прочитайте эти параметры один раз и передайте их вашей функции в качестве параметров. Эту функцию также можно немного упростить (и попытаться следовать соглашениям об именовании PEP8 ):

def func_power_3(param, x1, y):
    p1, p2 = param
    res = sum(y_i - (p1*x1_i)**p2 for x1_i, y_i in zip(x1, y))
    return res

а остальное будет

with open("power3X.txt","r") as infile:
    x1 = [float(line) for line in infile]

with open("power3Y.txt","r") as infile:
    y = [float(line) for line in infile]

xpl = numpy.arange(xmin, xmax, 0.1)   # no need for .tolist()
ypl = numpy.arange(ymin, ymax, 0.01)  # meshgrid can work with numpy.array's
xpl, ypl = numpy.meshgrid(xpl, ypl)

# we can form z with list comprehension
z = [[func_power_3([p1,p2], x1, y) for p1, p2 in zip(p1row, p2row)] 
                                   for p1row, p2row in zip(xpl, ypl)]

fig = plt.figure('Power 3')
ax = fig.gca(projection='3d')
surf=ax.plot_surface(xpl, ypl, z, rstride=8, cstride=8, alpha=0.3,cmap=cm.jet)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...