Es ist oft schwierig, intuitiv zu verstehen, wie das Ergebnis aussehen wird, selbst wenn es von einer Funktion erhalten wird. Das Zeichnen eines Diagramms ist daher der erste Schritt zum Analysieren und Denken. Das japanische Memo von matplotlib finden Sie unter hier. Die Handlung von Sympy ist hier. Offiziell Ich hatte Probleme, als ich es mir ansah.
import
import sympy as sym
sym.init_printing()
Pi = sym.S.Pi #Pi
E = sym.S.Exp1 #Boden des natürlichen Logarithmus
I = sym.S.ImaginaryUnit #Imaginäre Einheit
#Definition der zu verwendenden Variablen(Alle ein unterer Buchstabe ist ein Symbol)
(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) = sym.symbols('a b c d e f g h i j k l m n o p q r s t u v w x y z')
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
Die Liste der Farben wurde von einem anderen Programm vorgeneriert, sodass es sich um einen Ring mit konstanter Helligkeit im L * a * b * -Farbraum handelt. Farbschwäche wird nicht berücksichtigt, da sie einen Sicherheitsabstand für den Kontrast und nicht für die Lebendigkeit der Farbe bietet. Jede Liste besteht aus 37 HEX-Zeichenfolgen. Die Zahl 37 wurde ausgewählt, weil sie der Primzahl 36 am nächsten kommt. Dies ist die Zahl, die in einer Runde um 360 Grad um 10 Grad vorrückt. (Wenn es 37 ist, steigt es um 9,73 Grad pro Eins.) Da es sich um eine Primzahl handelt, unabhängig davon, wie Sie die Anfangsfarbe und die Anzahl der Schritte auswählen (es muss sich um eine primitive Wurzel handeln), handelt es sich immer um eine ** Patrouillengruppe **, die nacheinander 37 Farben durchläuft. Dies ist eine intuitive Übereinstimmung, bei der die Phase um etwa 10 Schritte * 10 Grad voranschreitet. So viel wie möglich erscheint nicht dieselbe Farbe und der Zyklus ist lang.
def generator_p(start): #Ein Generator zum Generieren von Farben in der Reihenfolge, in der ein Argument angegeben wird.
prime = 37 #Anzahl der Listen(Da es sich um eine Primzahl handelt, ist dies immer die maximale Periode, unabhängig davon, was Sie für das Primitiv angeben.)
primitive = 8 #Quelle(Der Farbton pro Schritt ist primitiv* 37/Gehen Sie 360 Grad)
g0 = start #Startquelle(Was tatsächlich zurückgegeben wird, ist g0* primitive)
while True:
val = yield g0
if val: #Wenn ein Argument an den Generator übergeben wird, wird es als Startquelle zurückgesetzt.
g0 = val
g0 += primitive
if g0 >= prime: #Nimm den Überschuss
g0 -= prime
gen_hexnum = generator_p(0) #Geben Sie die Anfangsfarbe in das Argument ein
gen_hexnum.__next__() #Generatorinitialisierung
def hexNum(num, type): #Liste der Farben
#Grundfarbe(Eine ruhige Farbe, die universell auf weißem Hintergrund verwendet werden kann)
color_basic = ['#9c1954', '#9e1a46', '#9d1e38', '#9a252a', '#962d1c', '#8f350d', '#873c00',
'#7d4300', '#734900', '#674f00', '#5b5300', '#4d5700', '#3e5b00', '#2b5d00',
'#0f6009', '#00611c', '#00632b', '#00643a', '#006449', '#006558', '#006567',
'#006575', '#006482', '#00648e', '#006298', '#0060a0', '#005ea6', '#005baa',
'#0056aa', '#0051a9', '#2f4ca4', '#50459d', '#673d94', '#78358a', '#862d7d', '#902470', '#981e62']
#Hoch gesättigte Farben(Es fällt auf, aber Sie sollten es nicht oft benutzen.)
color_vivid = ['#ffadc7', '#ffadbc', '#ffaeb2', '#ffb0a8', '#ffb29e', '#ffb596', '#f9b88f',
'#f1bc8a', '#e9bf86', '#dfc385', '#d5c685', '#caca87', '#becd8b', '#b2cf90',
'#a6d298', '#99d4a0', '#8dd5aa', '#80d7b4', '#74d7bf', '#6ad8ca', '#61d8d5',
'#5bd7e0', '#59d6e9', '#5dd5f2', '#65d3f9', '#71d1ff', '#7fceff', '#8ecbff',
'#9ec8ff', '#afc4ff', '#bec1ff', '#cdbdfd', '#dab9f7', '#e6b6ef', '#f0b3e6', '#f9b0dc', '#ffaed2']
#Helle Farbe(Nicht auf weißem Hintergrund verwendet. Angenommen, auf einem schwarzen Hintergrund verwendet zu werden.)
color_thin = ['#ffc3d5', '#ffc3cd', '#ffc3c5', '#ffc4be', '#ffc6b7', '#ffc8b1', '#fbcaac',
'#f5cca9', '#efcfa6', '#e8d2a5', '#e0d4a5', '#d8d7a6', '#cfd9a9', '#c6dbad',
'#bdddb3', '#b5deb9', '#ace0c0', '#a5e0c7', '#9ee1cf', '#98e1d7', '#94e1df',
'#92e1e6', '#92e0ed', '#94dff4', '#99def9', '#9fdcfd', '#a7daff', '#b1d8ff',
'#bbd5ff', '#c5d3ff', '#cfd0ff', '#dacdfc', '#e3cbf7', '#ecc8f2', '#f3c6eb', '#f9c5e4', '#fec4dc']
if (type == 'thin'):
hex_list = color_thin
elif (type == 'vivid'):
hex_list = color_vivid
else:
hex_list = color_basic
if num is not None:
gen_hexnum.send(num)
return hex_list[gen_hexnum.__next__()]
def plot(func, xrange, ylim=None, xlog=None, ylog=None, cn=None, ct='basic', close=None, figs=None, simbol=x):
if figs:
plt.figure(figsize=figs)
X = np.arange(xrange[0], xrange[1], xrange[2])
if hasattr(func, "subs"): # sympy
Y = [func.subs([(simbol, K)]) for K in X]
else: # scipy
Y = [func(K) for K in X]
if ylim:
plt.ylim(ylim)
if xlog:
plt.xscale('log')
else:
plt.xscale('linear')
if ylog:
plt.yscale('log')
else:
plt.yscale('linear')
plt.plot(X, Y, color=hexNum(cn, ct))
if close:
plt.show()
plt.close()
Die einfache Datei matplotlib.plot ist verwirrend, daher habe ich eine Funktion erstellt, die nur häufig verwendete Argumente umschließt. Es ist einfacher zu verwenden, wenn Sie die Funktion, Breite und Farbe angeben und dann danach fragen.
F = sym.sin(x)/x
G = sym.cos(x)/x
plot(F, (-10, 10, 0.1), cn=0, figs=(10, 6))
plot(G, (-10, 10, 0.1))
plot(F+0.2, (-10, 10, 0.1))
plot(F+0.4, (-10, 10, 0.1))
plot(F+0.6, (-10, 10, 0.1))
plot(F+0.8, (-10, 10, 0.1))
plot(F+1.0, (-10, 10, 0.1))
def A(x):
return np.sin(x)/x
plot(A, (-10, 10, 0.1))
plot(lambda X: (X/9.0)**2, (-10, 10, 0.1), (-0.5, 1.5), close=True)
Um Sympy bequem zu verwenden, möchte ich alle unteren Buchstaben als Symbole verwenden Funktionsnamen und Schleifenvariablen werden absichtlich großgeschrieben. Farbcodierungseffekt nach Farbe, automatische Beurteilung von Sympy- und Numpy-Funktionen durch Hasattr, Mit dem Argument close müssen am Ende alle Optionen zusammen geschrieben werden. Ich bin zufrieden, weil ich es ganz intuitiv zeichnen kann. In der Grafik sind die Pole von $ \ frac {\ cos (x)} {x} $ jedoch seltsam. Die Atmosphäre ist, dass die Linie in der Mitte von $ - \ infty \ longrightarrow \ infty $ gezogen wird. Gibt es eine Lösung?
def plotp(func, t_range=(-4, 4, 100), axis=[-4, 4, -4, 4],
xlog=None, ylog=None, cn=None, ct='basic', close=None, figs=None, simbol=t):
if figs:
plt.figure(figsize=figs)
X, Y = func
t_ndarray = np.linspace(t_range[0], t_range[1], t_range[2]) # ndarray
if hasattr(X, "subs"): # sympy
Xp = np.array([float(sym.N(X.subs([(simbol, T)]))) for T in t_ndarray])
Yp = np.array([float(sym.N(Y.subs([(simbol, T)]))) for T in t_ndarray])
else: # scipy
Xp = [X(K) for K in t_ndarray]
Yp = [Y(K) for K in t_ndarray]
plt.axis(axis)
if xlog:
plt.xscale('log')
else:
plt.xscale('linear')
if ylog:
plt.yscale('log')
else:
plt.yscale('linear')
plt.plot(Xp, Yp, color=hexNum(cn, ct))
if close:
plt.show()
plt.close()
Der Unterschied zu plot () besteht darin, dass Func als Liste von zwei Funktionen übergeben wird und eine Achse hinzugefügt wird, die die x- und y-Bereiche angibt. Konventionell ist t das Standardsymbol. Als dritter Bereich von t wird er auch durch die Anzahl der Unterteilungen anstelle der Schrittgröße angegeben.
X = t**2 * sym.sin(t)
Y = t**2 * sym.cos(t)
plotp([X, Y], (-4 * np.pi, 4 * np.pi, 400), [-100, 100, -100, 100], figs=(6, 6), close=True)
plotp([lambda T: T * np.sin(T), lambda T: T * np.cos(T)], (-4 * np.pi, 4 * np.pi, 400), [-12, 12, -10, 10],
cn=14, figs=(6, 6), close=True)
Sowohl Sympy als auch Scipy funktionierten.
Es ist eine Funktion, die im Format $ F (x, y) = 0 $ ausgedrückt wird. Es scheint schwierig zu sein, implizite Funktionen direkt zu handhaben. Verwenden Sie also sympy's plot_implicit so wie es ist.
F = x**3 + y**2 -1
sym.plot_implicit(F, (x, -2, 2), (y, -2, 2), line_color=hexNum(2, 'basic'))
Dies ist eine elliptische Kurvengleichung. Die Farbe scheint brauchbar zu sein, aber es ist hell.
F = x**3 - 2 * x + y**2 > 0
sym.plot_implicit(F, (x, -2, 2), (y, -2, 2), line_color=hexNum(2, 'thin'))
Der Vorteil ist, dass Ungleichung verwendet werden kann.
Eine Funktion der Form $ z = f (x, y) $.
from matplotlib import cm
def plot3D(func, xrange=(-2, 2, 0.1), yrange=(-2, 2, 0.1), ptype='plot', simbol=[x, y]):
fig = plt.figure()
ax = Axes3D(fig)
if ptype == 'plot':
ax.plot(func[0], func[1], func[2])
plt.show()
plt.close()
return
X = np.arange(xrange[0], xrange[1], xrange[2])
Y = np.arange(yrange[0], yrange[1], yrange[2])
Xmesh, Ymesh = np.meshgrid(X, Y)
if hasattr(func, "subs"): # sympy
Z = np.array([np.array([float(sym.N(func.subs([(simbol[0], K), (simbol[1], L)]))) for K in X]) for L in Y])
else: # scipy
Z = func(Xmesh, Ymesh)
if ptype == 'surface':
ax.plot_surface(Xmesh, Ymesh, Z, cmap=cm.bwr)
elif ptype == 'wireframe':
ax.plot_wireframe(Xmesh,Ymesh, Z)
elif ptype == 'contour':
ax.contour3D(X, Y, Z)
plt.show()
plt.close()
plot3D(lambda T, U: T * U * np.sin(T), (-4, 4, 0.25), (-4, 4, 0.25), 'surface')
plot3D((x ** 2 - 3 - y ** 2), (-4, 4, 0.25), (-4, 4, 0.25), 'surface')
plot3D((x ** 2 - 3 - y ** 2), (-4, 4, 0.25), (-4, 4, 0.25), 'wireframe')
plot3D((x ** 2 - 3 - y ** 2), (-4, 4, 0.25), (-4, 4, 0.25), 'contour')
Die Standardfarbe wird für 3D verwendet, da es besser ist, die Höhen und Tiefen mit einem Unterschied in der Helligkeit zu sehen. Ich habe die Funktion des Pferdesattels aufgezeichnet, die häufig in der Figur des Universums mit negativer Krümmung erscheint.
def plotp3(func, simbol=[t], rangeL=[(-4, 4, 100)]):
X, Y, Z = func
t1 = simbol[0]
if len(simbol) >= 2:
u1 = simbol[1]
t_rangeL = rangeL[0]
t_ndarray = np.linspace(t_rangeL[0], t_rangeL[1], t_rangeL[2]) # ndarray
if len(rangeL) >= 2:
u_rangeL = rangeL[1]
u_ndarray = np.linspace(u_rangeL[0], u_rangeL[1], u_rangeL[2]) # ndarray
if len(rangeL) == 1:
Xp = np.array([float(sym.N(X.subs([(t1, T)]))) for T in t_ndarray])
Yp = np.array([float(sym.N(Y.subs([(t1, T)]))) for T in t_ndarray])
Zp = np.array([float(sym.N(Z.subs([(t1, T)]))) for T in t_ndarray])
else:
Xp = np.array([float(sym.N(X.subs([(t1, T), (u1, U)]))) for T in t_ndarray for U in u_ndarray])
Yp = np.array([float(sym.N(Y.subs([(t1, T), (u1, U)]))) for T in t_ndarray for U in u_ndarray])
Zp = np.array([float(sym.N(Z.subs([(t1, T), (u1, U)]))) for T in t_ndarray for U in u_ndarray])
fig = plt.figure()
ax = Axes3D(fig)
ax.plot(Xp, Yp, Zp)
plt.show()
plt.close()
X = 2*sym.cos(t)
Y = 5*sym.sin(t)
Z = t
plotp3([X, Y, Z], [t], [(-5 * np.pi, 5 * np.pi, 200)])
X = (5+2*sym.cos(t))*sym.cos(u)
Y = (5+2*sym.sin(u))*sym.sin(u)
Z = 2*sym.sin(t)-u/sym.oo
plotp3([X, Y, Z], [t, u], [(-np.pi, np.pi, 40), (-np.pi, np.pi, 40)])
Ich werde müde von dieser Gegend. 3D ist Sympy-Standard, also ist es okay.
X = 2*sym.cos(t)
Y = 5*sym.sin(t)
Z = t
sym.plotting.plot3d_parametric_line(X, Y, Z, (t, -5*np.pi, 5*np.pi))
X = (5+2*sym.cos(t))*sym.cos(u)
Y = (5+2*sym.sin(u))*sym.sin(u)
Z = 2*sym.sin(t)-u/sym.oo
sym.plotting.plot3d_parametric_surface(X, Y, Z, (t, -np.pi, np.pi), (u, -np.pi, np.pi))
Recommended Posts