0

I am new to programming in python. I am trying to show a surface plot by modifying an example found on the matplotlib website. Can you tell me what's wrong?

My code is:

import matplotlib.pyplot as plt
from matplotlib import cm
import numpy

def H(n, f, l, delta, H_abs, H_ph):
    c0 = 2.99796e8
    n0 = 1.00027 + 0j
    n1 = complex(n[0], n[1])

    Sum = 0
    for i in range(1, delta+1):
        Sum = Sum + ((n0-n1)*exp(complex(0,-1*2*pi*f*n1*l/c0))/(n1+n0))**i

    H_Theo = 4*n0*n1*exp(complex(0,2*pi*f*l)*(n0-n1)/c0)*(1+Sum)/(n0+n1)

    M = abs(H_Theo) - H_abs
    A = cmath.phase(H_Theo) - H_ph

    return abs(M) + abs(A)

freq = 1213188709257.4814
l_real = 6.77e-4
d = 0
H_abs = 0.798653104536778
H_ph = 2.1845744701729926

n_test = numpy.arange(1.5, 2.5, 0.01).tolist()
k_test = numpy.arange(-0.05, 0.05, 0.001).tolist()

X = n_test
Y = k_test
X, Y = numpy.meshgrid(X, Y)

errore = []
for i in range(len(n_test)):
    errore.append(H([X[i],Y[i]], freq, l_real, d, H_abs, H_ph))

Z = errore

fig2 = plt.figure()
az = fig2.gca(projection='3d')
az.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = az.contour(X, Y, Z, zdir='z', offset=min(Z)-1, cmap=cm.coolwarm)
cset = az.contour(X, Y, Z, zdir='x', offset=min(X)-1, cmap=cm.coolwarm)
cset = az.contour(X, Y, Z, zdir='y', offset=max(Y)+0.05, cmap=cm.coolwarm)

az.set_xlabel('n')
az.set_xlim(min(X)-1, max(X)+1)
az.set_ylabel('k')
az.set_ylim(min(Y)-0.05, max(Y)+0.05)
az.set_zlabel('Err')
az.set_zlim(min(Z)-1, max(Z)+1)

plt.show()

The error I get is:

n1 = complex(n[0], n[1])
TypeError: only length-1 arrays can be converted to Python scalars

I have seen other Q&A on the subject but I was unable to solve the problem, anyway.

Maybe the question is trivial but I will really appreciate any help in order to be able to see the graph that, at the end, should turn out to be similar to this one: http://matplotlib.org/examples/mplot3d/contour3d_demo3.html

0

1 Answer 1

1

Your problem is that X[i] and Y[i] are 1-d arrays that you pass in to H as n. I.e., n = [X[i], Y[i]]. Then you call complex(n[0], n[1]) which expects scalar arguments, not arrays. If you intend for n to be a 1-d array of complex numbers, you can write n = n[0] + 1j*n[1]. You still need modifications to the rest of your code, however. You're missing some imports and seem to have assumed "from numpy import *"

Anyway, I've made enough modifications to get it to run and plot something, but I really doubt this is what you're looking for. You need to think about what function it is you're trying to plot.

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy

def H(n, f, l, delta, H_abs, H_ph):
    c0 = 2.99796e8
    n0 = 1.00027 + 0j
    n1 = n[0] + 1j * n[1]

    Sum = 0
    for i in range(1, delta+1):
        Sum = Sum + ((n0-n1)*numpy.exp(-1*2*numpy.pi*f*n1*l/c0)/(n1+n0))**i

    H_Theo = 4*n0*n1*numpy.exp(2*numpy.pi*f*l*(n0-n1)/c0)*(1+Sum)/(n0+n1)

    M = numpy.abs(H_Theo) - H_abs
    A = numpy.angle(H_Theo) - H_ph

    return abs(M) + abs(A)

freq = 1213188709257.4814
l_real = 6.77e-4
d = 0
H_abs = 0.798653104536778
H_ph = 2.1845744701729926

n_test = numpy.arange(1.5, 2.5, 0.01).tolist()
k_test = numpy.arange(-0.05, 0.05, 0.001).tolist()

X = n_test
Y = k_test
X, Y = numpy.meshgrid(X, Y)

errore = []
for i in range(len(n_test)):
    errore.append(H([X[i],Y[i]], freq, l_real, d, H_abs, H_ph))

Z = errore

fig2 = plt.figure()
az = fig2.gca(projection='3d')
az.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = az.contour(X, Y, Z, zdir='z', offset=numpy.min(Z)-1, cmap=cm.coolwarm)
cset = az.contour(X, Y, Z, zdir='x', offset=numpy.min(X)-1, cmap=cm.coolwarm)
cset = az.contour(X, Y, Z, zdir='y', offset=numpy.max(Y)+0.05, cmap=cm.coolwarm)

az.set_xlabel('n')
az.set_xlim(numpy.min(X)-1, numpy.max(X)+1)
az.set_ylabel('k')
az.set_ylim(numpy.min(Y)-0.05, numpy.max(Y)+0.05)
az.set_zlabel('Err')
az.set_zlim(numpy.min(Z)-1, numpy.max(Z)+1)

plt.show()
Sign up to request clarification or add additional context in comments.

3 Comments

Thank for your suggestion. Now there is a new error: Sum = Sum + ((n0-n1)*exp(complex(0,-1*2*pifn1*l/c0))/(n1+n0))**i TypeError: only length-1 arrays can be converted to Python scalars
Thenk you for your very fast answer. I have modified the code following your indications and a little bit more. Then I will look into the function but, for now, I have one more error: cset = az.contour(X, Y, Z, zdir='z', offset=min(Z)-1, cmap=cm.coolwarm) ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Replace set = az.contour(X, Y, Z, zdir='z', offset=min(Z)-1, cmap=cm.coolwarm) with cset = az.contour(X, Y, Z, zdir='z', offset=numpy.min(Z)-1, cmap=cm.coolwarm)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.