Plot graph with 4 equations consist of f(x,y, xy) - python

I'd like to plot a graph which contains 4 functions as shown below:
xy1: - 12.8 x - 0.108 y + xy >= -1.3824
xy2: - 40 x - 5 y + xy >= -200
xy3: - 40 x - 0.108 y + xy <= -4.32
xy4: - 12.8 x - 5 y + xy <= -64
I started off by generating data for x and y
import numpy as np
x = np.linspace(0, 5, 100)
y = np.linspace(0, 40, 100)
But then when I tried to plot the graph, I started to confuse about how should I reformulate the equations so that it is appropriate value for x, y, xy?
import matplotlib.pyplot as plt
plt.plot((-1.3824 + (12.8 * x) + (0.108 * y)), y) <--- this doesn't seems to be right
plt.show()

You can use contour for implicit function plotting. By the way I don't think you can plot multiple functions with inequality on the same graph because you have to show the ranges in the 2D plane, and they overlap each other.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 100)
y = np.linspace(0, 40, 100)
X, Y = np.meshgrid(x, y)
XY1 = (-12.8*X - 0.108*Y + X*Y) >= -1.3824
XY2 = - 40*X - 5*Y + X*Y >= -200
XY3 = - 40*X - 0.108*y + X*Y <= -4.32
XY4 = - 12.8*X - 5*Y + X*Y <= -64
plt.contour(X,Y, XY1)
plt.contour(X,Y, XY2)
plt.contour(X,Y, XY3)
plt.contour(X,Y, XY4)
plt.show()
================================================================
UPDATE:
Seems like sympy's plot_implicit works so much better. You may need to install it.
from sympy import plot_implicit, symbols, And
x, y = symbols('x y')
p1 = plot_implicit(And(-12.8*x - 0.108*y + x*y >= -1.3824), (x,0,5), (y,0,40))
p2 = plot_implicit(And(-40*x - 5*y + x*y >= -200), (x,0,5), (y,0,40))
p3 = plot_implicit(And(-40*x - 0.108*y + x*y <= -4.32), (x,0,5), (y,0,40))
p4 = plot_implicit(And(-12.8*x - 5*y + x*y <= -64), (x,0,5), (y,0,40))
Results:

you can use contourf:
import pylab as pl
import numpy as np
x, y = np.mgrid[-10:10:100j, -10:50:100j]
z1 = - 12.8 * x - 0.108 * y + x * y + 1.3824
z2 = - 40 * x - 5 * y + x * y + 200
z3 = - 40 * x - 0.108 * y + x * y + 4.32
z4 = - 12.8 * x - 5 * y + x * y + 64
fig, axes = pl.subplots(2, 2, figsize=(12, 8))
axes = axes.ravel()
axes[0].contourf(x, y, z1, levels=[0, 1e10], alpha=0.2, colors=["blue"])
axes[1].contourf(x, y, z2, levels=[0, 1e10], alpha=0.2, colors=["green"])
axes[2].contourf(x, y, z3, levels=[-1e10, 0], alpha=0.2, colors=["red"])
axes[3].contourf(x, y, z4, levels=[-1e10, 0], alpha=0.2, colors=["yellow"])
Here is the output:

Related

Reconstructing polynomials from scipy.interpolate.RectBivariateSpline

I have fitted a 2-D cubic spline using scipy.interpolate.RectBivariateSpline. I would like to access/reconstruct the underlying polynomials within each rectangular cell. How can I do this? My code so far is written below.
I have been able to get the knot points and the coefficients with get_knots() and get_coeffs() so it should be possible to build the polynomials, but I do not know the form of the polynomials that the coefficients correspond to. I tried looking at the SciPy source code but I could not locate the underlying dfitpack.regrid_smth function.
A code demonstrating the fitting:
import numpy as np
from scipy.interpolate import RectBivariateSpline
# Evaluate a demonstration function Z(x, y) = sin(sin(x * y)) on a mesh
# of points.
x0 = -1.0
x1 = 1.0
n_x = 11
x = np.linspace(x0, x1, num = n_x)
y0 = -2.0
y1 = 2.0
n_y = 21
y = np.linspace(y0, y1, num = n_y)
X, Y = np.meshgrid(x, y, indexing = 'ij')
Z = np.sin(np.sin(X * Y))
# Fit the sampled function using SciPy's RectBivariateSpline.
order_spline = 3
smoothing = 0.0
spline_fit_func = RectBivariateSpline(x, y, Z,
kx = order_spline, ky = order_spline, s = smoothing)
And to plot it:
import matplotlib.pyplot as plt
# Make axes.
fig, ax_arr = plt.subplots(1, 2, sharex = True, sharey = True, figsize = (12.0, 8.0))
# Plot the input function.
ax = ax_arr[0]
ax.set_aspect(1.0)
d_x = x[1] - x[0]
x_edges = np.zeros(n_x + 1)
x_edges[:-1] = x - (d_x / 2.0)
x_edges[-1] = x[-1] + (d_x / 2.0)
d_y = y[1] - y[0]
y_edges = np.zeros(n_y + 1)
y_edges[:-1] = y - (d_y / 2.0)
y_edges[-1] = y[-1] + (d_y / 2.0)
ax.pcolormesh(x_edges, y_edges, Z.T)
ax.set_title('Input function')
# Plot the fitted function.
ax = ax_arr[1]
ax.set_aspect(1.0)
n_x_span = n_x * 10
x_span_edges = np.linspace(x0, x1, num = n_x_span)
x_span_centres = (x_span_edges[1:] + x_span_edges[:-1]) / 2.0
#
n_y_span = n_y * 10
y_span_edges = np.linspace(y0, y1, num = n_y_span)
y_span_centres = (y_span_edges[1:] + y_span_edges[:-1]) / 2.0
Z_fit = spline_fit_func(x_span_centres, y_span_centres)
ax.pcolormesh(x_span_edges, y_span_edges, Z_fit.T)
x_knot, y_knot = spline_fit_func.get_knots()
X_knot, Y_knot = np.meshgrid(x_knot, y_knot)
# Plot the knots.
ax.scatter(X_knot, Y_knot, s = 1, c = 'r')
ax.set_title('Fitted function and knots')
plt.show()

How to draw heatmap based on density map

Im trying to draw a heatmap from a given distribution. Ex, a normal distribution of a 2D array will look like this:
If i have another density graph like this:
How can i draw a heatmap that look like the 1st one. This is the code i used to draw the 1st heat map:
output_width = 40
output_height = 40
p_x = 20
p_y = 20
sigma = 1
X1 = np.linspace(0, output_width, output_width)
Y1 = np.linspace(0, output_height, output_height)
[X, Y] = np.meshgrid(X1, Y1)
X = X - floor(p_x)
Y = Y - floor(p_y)
D2 = X * X + Y * Y
E2 = 2.0 * sigma ** 2
Exponent = D2 / E2
heatmap = np.exp(-Exponent)
heatmap = (heatmap - heatmap.min()) / (heatmap.max() - heatmap.min())
plt.imshow(heatmap)
output_width = 40
output_height = 40
mu = 0; sigma=0.1
x, y = np.meshgrid(np.linspace(-1, 1, 40),
np.linspace(-1, 1, 40))
dst = np.sqrt(x**2+y**2)
# lower normal part of gaussian
normal = 1/(2.0 * np.pi * sigma**2)
# Calculating Gaussian filter
gauss = np.exp(-((dst-mu)**2 / (2.0 * sigma**2))) * normal
plt.imshow(gauss)
Gives:

Plotting a vector field using quiver

I'm trying to reproduce a 2D vector map with components
v = 100/a * exp(-1/a^2 * ((x+0.55)^2+y^2))(-y,x) - 100/a * exp(-1/a^2 * ((x-0.55)^2+y^2))(-y,x)
and here are my codes. It did not give the map I want (see attached vector map). Could someone please help me with it?
import numpy as np
import matplotlib.pyplot as plt
import math
grid_resolution = 25
grid_size = 2*grid_resolution+1
a = 0.2
x = np.linspace(-1,1,grid_size)
y = np.linspace(-1,1,grid_size)
X,Y = np.meshgrid(x, y)
vx = np.zeros((grid_size,grid_size))
vy = np.zeros((grid_size,grid_size))
for i in range(0,grid_size):
for j in range(0,grid_size):
x0 = x[j]
y0 = y[i]
xx = (x0 + 0.55) ** 2 + y0 ** 2
yy = (x0 - 0.55) ** 2 + y0 ** 2
expf1 = math.exp(-xx / (a ** 2))
expf2 = math.exp(-yy / (a ** 2))
vx[i,j] = 100 / a * (-expf1 + expf2) * y0
vy[i,j] = 100 / a * (expf1 - expf2) * x0
fig, ax = plt.subplots()
ax.quiver(X, Y, vx, vy)
ax.set_aspect('equal')
plt.show()
In the last passage, when you compute vx[i,j] and vy[i,j], you are computing vector field components in (x0, y0), while you should compute it in the current point, so (x0 ± 0.55, y0). Moreover, you should change the sign of vx and vy in order to draw a vector field like the one you linked.
import numpy as np
import matplotlib.pyplot as plt
import math
grid_resolution = 25
grid_size = 2*grid_resolution + 1
a = 0.2
x = np.linspace(-1, 1, grid_size)
y = np.linspace(-1, 1, grid_size)
X, Y = np.meshgrid(x, y)
vx = np.zeros((grid_size, grid_size))
vy = np.zeros((grid_size, grid_size))
for i in range(0, grid_size):
for j in range(0, grid_size):
x0 = x[j]
y0 = y[i]
xx = (x0 + 0.55)**2 + y0**2
yy = (x0 - 0.55)**2 + y0**2
expf1 = math.exp(-xx/(a**2))
expf2 = math.exp(-yy/(a**2))
vx[i, j] = -100/a*(-expf1 + expf2)*y0
if x0 > 0:
vy[i, j] = -100/a*(expf1 - expf2)*(x0 - 0.55)
else:
vy[i, j] = -100/a*(expf1 - expf2)*(x0 + 0.55)
fig, ax = plt.subplots()
ax.quiver(X,Y,vx,vy)
ax.set_aspect('equal')
plt.show()

Scipy odeint. Gravitational motion

I solve the motion in gravitational field around the sun with scipy and mathplotlib and have a problem. My solution is not correct. It is not like in example. Formulas that I used.
from scipy.integrate import odeint
import scipy.constants as constants
import numpy as np
import matplotlib.pyplot as plt
M = 1.989 * (10 ** 30)
G = constants.G
alpha = 30
alpha0 = (alpha / 180) * np.pi
v00 = 0.7
v0 = v00 * 1000
def dqdt(q, t):
x = q[0]
y = q[2]
ax = - G * M * (x / ((x ** 2 + y ** 2) ** 1.5))
ay = - G * M * (y / ((x ** 2 + y ** 2) ** 1.5))
return [q[1], ax, q[3], ay]
vx0 = v0 * np.cos(alpha0)
vy0 = v0 * np.sin(alpha0)
x0 = -150 * (10 ** 11)
y0 = 0 * (10 ** 11)
q0 = [x0, vx0, y0, vy0]
N = 1000000
t = np.linspace(0.0, 100000000000.0, N)
pos = odeint(dqdt, q0, t)
x1 = pos[:, 0]
y1 = pos[:, 2]
plt.plot(x1, y1, 0, 0, 'ro')
plt.ylabel('y')
plt.xlabel('x')
plt.grid(True)
plt.show()
How can I fix this?
Maybe you can tell me solution with another method for example with Euler's formula or with using other library.
I will be very greatful if you help me.

scipy.odeint strange behavior

Here is my code to solve differential equation dy / dt = 2 / sqrt(pi) * exp(-x * x) to plot erf(x).
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import numpy as np
import math
def euler(df, f0, x):
h = x[1] - x[0]
y = [f0]
for i in xrange(len(x) - 1):
y.append(y[i] + h * df(y[i], x[i]))
return y
def i(df, f0, x):
h = x[1] - x[0]
y = [f0]
y.append(y[0] + h * df(y[0], x[0]))
for i in xrange(1, len(x) - 1):
fn = df(y[i], x[i])
fn1 = df(y[i - 1], x[i - 1])
y.append(y[i] + (3 * fn - fn1) * h / 2)
return y
if __name__ == "__main__":
df = lambda y, x: 2.0 / math.sqrt(math.pi) * math.exp(-x * x)
f0 = 0.0
x = np.linspace(-10.0, 10.0, 10000)
y1 = euler(df, f0, x)
y2 = i(df, f0, x)
y3 = odeint(df, f0, x)
plt.plot(x, y1, x, y2, x, y3)
plt.legend(["euler", "modified", "odeint"], loc='best')
plt.grid(True)
plt.show()
And here is a plot:
Am I using odeint in a wrong way or it's a bug?
Notice that if you change x to x = np.linspace(-5.0, 5.0, 10000), then your code works. Therefore, I suspect the problem has something to do with exp(-x*x) being too small when x is very small or very large. [Total speculation: Perhaps the odeint (lsoda) algorithm adapts its stepsize based on values sampled around x = -10 and increases the stepsize in such a way that values around x = 0 are missed?]
The code can be fixed by using the tcrit parameter, which tells odeint to pay special attention around certain critical points.
So, by setting
y3 = integrate.odeint(df, f0, x, tcrit = [0])
we tell odeint to sample more carefully around 0.
import matplotlib.pyplot as plt
import scipy.integrate as integrate
import numpy as np
import math
def euler(df, f0, x):
h = x[1] - x[0]
y = [f0]
for i in xrange(len(x) - 1):
y.append(y[i] + h * df(y[i], x[i]))
return y
def i(df, f0, x):
h = x[1] - x[0]
y = [f0]
y.append(y[0] + h * df(y[0], x[0]))
for i in xrange(1, len(x) - 1):
fn = df(y[i], x[i])
fn1 = df(y[i - 1], x[i - 1])
y.append(y[i] + (3 * fn - fn1) * h / 2)
return y
def df(y, x):
return 2.0 / np.sqrt(np.pi) * np.exp(-x * x)
if __name__ == "__main__":
f0 = 0.0
x = np.linspace(-10.0, 10.0, 10000)
y1 = euler(df, f0, x)
y2 = i(df, f0, x)
y3 = integrate.odeint(df, f0, x, tcrit = [0])
plt.plot(x, y1)
plt.plot(x, y2)
plt.plot(x, y3)
plt.legend(["euler", "modified", "odeint"], loc='best')
plt.grid(True)
plt.show()

Categories