Create the equivalent of np.meshgrid using for loops - python

This code outputs a plot of e^(-r^2) on a 2-D x,y grid :
import numpy as np
import matplotlib.pyplot as plt
x1d = np.arange(-3, 3, 0.006)
y1d = np.arange(-3, 3, 0.006)
x2d, y2d = np.meshgrid(x1d, y1d)
r2d = x2d**2 + y2d**2
z = np.exp(-r2d)
plt.imshow(z, extent = (3, -3 , 3 , -3))
plt.title("A 2-D Image plot")
plt.xlabel('x axis')
plt.ylabel('y axis')
plt.savefig('2dexp_array.pdf', format ='pdf')
plt.show(block = False)
I want to change the code so that instead of using np.meshgrid , it uses for loops to generate the 2d grid space.
Something like :
import numpy as np
import matplotlib.pyplot as plt
x1d = np.arange(-3, 3, 0.006)
y1d = np.arange(-3, 3, 0.006)
z = np.zeros([2000, 2000])
and then using for loops to replace the zeros in z with the correct values according to x1d , y1d.
But I'm not sure how to use a for loop to mirror the function of meshgrid.
If someone could point me in the right direction I would appreciate it
Thanks

This should do:
for i,x in enumerate(x1d):
for j,y in enumerate(y1d):
z[i,j] = np.exp(-(x**2 + y**2))

Related

Show integer points in coordinate system

Say I have a simple pyplot:
import matplotlib.pyplot as plt
plt.plot([-1, -4.5, 3.14, 1])
plt.show()
Which generates the following:
How do I show all Integer points in the graph, so it looks like:
You can use plt.xlim/plt.ylim to get the limits and numpy.meshgrid to generate the points, then plt.scatter to plot them:
import matplotlib.pyplot as plt
plt.plot([-1, -4.5, 3.14, 1])
x0,x1 = plt.xlim()
y0,y1 = plt.ylim()
import numpy as np
X,Y = np.meshgrid(np.arange(round(x0), round(x1)+1),
np.arange(round(y0), round(y1)+1))
plt.scatter(X,Y)
output:
Here's a very primitive method.
import matplotlib.pyplot as plt
import numpy as np
plt.plot([-1, -4.5, 3.14, 1])
# Get interger points of x and y within the axes
xlim = np.round(plt.xlim(), 0)
list_x = np.arange(xlim[0], xlim[1]+1)
ylim = np.round(plt.ylim(), 0)
list_y = np.arange(ylim[0], ylim[1]+1)
# Get mesh grids for the points
mesh_x, mesh_y = np.meshgrid(list_x, list_y)
# Make grids to vectors
list_x = mesh_x.flatten()
list_y = mesh_y.flatten()
# Plot points
plt.plot(list_x, list_y, ls="none", marker=".")
plt.show()
import matplotlib.pyplot as plt
l = [-1, -4.5, 3.14, 1]
plt.plot(l)
integers = [[x, y] for x in range(len(l)) for y in range(math.floor(min(l)), math.ceil(max(l)))]
x_int_points, y_int_points = list(zip(*integers))
plt.scatter(x=x_int_points, y=y_int_points)
plt.show()
Generalized:
def plot_with_grid(l):
integers = [[x, y] for x in range(len(l)) \
for y in range(math.floor(min(l)),
math.ceil(max(l)))]
x_int_points, y_int_points = list(zip(*integers))
plt.plot(l)
plt.scatter(x=x_int_points, y=y_int_points)
plt.show()

Plot lines to x and y values of maximum in graph with spline interpolation [duplicate]

This question already has answers here:
Plot a horizontal line on a given plot
(7 answers)
How to draw vertical lines on a given plot
(6 answers)
Closed 1 year ago.
I'd like to plot a graph and highlight its local maximum by drawing a dotted line back to x and y axis, and displaying the values of both.
For example some data:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import make_interp_spline
x_ = np.array([1, 2.5, 2.7, 8, 3])
y_ = np.array([1, 2, 3, 4, 5, 6])
spline = make_interp_spline(x_, y_)
x = np.linspace(x_.min(), x_.max(), 500)
y = spline(x)
xmax = x[np.argmax(y)]
ymax = y.max()
plt.plot(x, y)
plt.plot(xmax,ymax,'o')
plt.show()
How do I do this?
Thanks in advance
The general code is OK, but there are two major mistakes:
1- x should be sorted
2- x and y should be of same size
Working version of the code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import make_interp_spline
x_ = np.array([1, 2.5, 2.7, 3, 8])
y_ = np.array([1, 2, 3, 5, 4])
spline = make_interp_spline(sorted(x_), y_)
x = np.linspace(x_.min(), x_.max(), 500)
y = spline(x)
xmax = x[np.argmax(y)]
ymax = y.max()
plt.plot(x_, y_, 'o')
plt.plot(x, y)
plt.plot(xmax,ymax,'s')
# annotations
plt.axhline(ymax, ls=':', c='k')
plt.axvline(xmax, ls=':', c='k')
plt.text(xmax, ymax*0.95, f'({round(xmax,2)}, {round(ymax,2)})')
plt.show()

fill the common area under both curve

How I can fill the common area under both the curve?
import matplotlib.pyplot as plt
import numpy as np
import scipy.special as sp
x = np.linspace(-4, 4, num=1000)
r = abs(x)
zeta = 1.0
psi_STO = (zeta**3 / np.pi)**(0.5) * np.exp(-zeta * r)
plt.figure(figsize=(4, 3))
plt.plot(x, psi_STO, color="C0")
plt.plot(x + 3, psi_STO, color="C0")
plt.show()
If I use:
plt.fill_betweenx(psi_STO, -1, 4, color="C1")
I am getting a plot as:
You can use fill_between. As your Xs are not aligned, you need to make a bit of calculations first to find the common range. This will depend on the number of points in the linspace. Here, I computed it manually: as the shift is of 3, there are 375 points difference (250 per unit).
import matplotlib.pyplot as plt
import numpy as np
import scipy.special as sp
x = np.linspace(-4, 4, num=1000)
r = abs(x)
zeta = 1.0
psi_STO = (zeta**3 / np.pi)**(0.5) * np.exp(-zeta * r)
plt.figure(figsize=(4, 3))
plt.plot(x, psi_STO, color="C0")
plt.plot(x + 3, psi_STO, color="C0")
x_common = (x+3)[:-375]
min_common = np.min([psi_STO[:-375], psi_STO[375:]], axis=0)
plt.plot(x_common, min_common, color='r')
plt.fill_between(x_common,min_common, color="#FFB0B0")
plt.show()
output:
This?
dx = 3 # x shift
di = int(dx/(x[1]-x[0])) # index shift
plt.fill_between(x[di:], np.minimum(psi_STO[:-di], psi_STO[di:]))

Matplotlib contour hatching not working if only two levels was used

I am trying to plot hatches over contours lines that
statisfy certian criteria folliwng the example found here. Yet, I got regular contours (the yellow lines) instead of the hatches. Any ideas how to resolve that. Thanks
import matplotlib.pyplot as plt
import numpy as np
# invent some numbers, turning the x and y arrays into simple
# 2d arrays, which make combining them together easier.
x = np.linspace(-3, 5, 150).reshape(1, -1)
y = np.linspace(-3, 5, 120).reshape(-1, 1)
z = np.cos(x) + np.sin(y)
# we no longer need x and y to be 2 dimensional, so flatten them.
x, y = x.flatten(), y.flatten()
fig2, ax2 = plt.subplots()
n_levels = 6
a=ax2.contourf(x, y, z, n_levels)
fig2.colorbar(a)
[m,n]=np.where(z > 0.5)
z1=np.zeros(z.shape)
z1[m,n]=99
cs = ax2.contour(x, y, z1,2,hatches=['','.'])
plt.show()enter code here
Use contourf() with proper parameters to get useful plot with hatching. See important comment within the working code below:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3, 5, 150).reshape(1, -1)
y = np.linspace(-3, 5, 120).reshape(-1, 1)
z = np.cos(x) + np.sin(y)
x, y = x.flatten(), y.flatten()
fig2, ax2 = plt.subplots()
n_levels = 6
a = ax2.contourf(x, y, z, n_levels)
fig2.colorbar(a)
[m,n] = np.where(z > 0.5)
z1=np.zeros(z.shape)
z1[m, n] = 99
# use contourf() with proper hatch pattern and alpha value
cs = ax2.contourf(x, y, z1 ,3 , hatches=['', '..'], alpha=0.25)
plt.show()
The output plot:

Plotting a polynomial using Matplotlib and coeffiecients

My code is:
import numpy as np
import matplotlib as plt
polyCoeffiecients = [1,2,3,4,5]
plt.plot(PolyCoeffiecients)
plt.show()
The result for this is straight lines that describe the points in 1,2,3,4,5 and the straight lines between them, instead of the polynomial of degree 5 that has 1,2,3,4,5 as its coeffiecients ( P(x) = 1 + 2x + 3x + 4x + 5x)
How am i suppose to plot a polynomial with just its coefficients?
Eyzuky, see if this is what you want:
import numpy as np
from matplotlib import pyplot as plt
def PolyCoefficients(x, coeffs):
""" Returns a polynomial for ``x`` values for the ``coeffs`` provided.
The coefficients must be in ascending order (``x**0`` to ``x**o``).
"""
o = len(coeffs)
print(f'# This is a polynomial of order {o}.')
y = 0
for i in range(o):
y += coeffs[i]*x**i
return y
x = np.linspace(0, 9, 10)
coeffs = [1, 2, 3, 4, 5]
plt.plot(x, PolyCoefficients(x, coeffs))
plt.show()
You could approximately draw the polynomial by getting lots of x-values and using np.polyval() to get the y-values of your polynomial at the x-values. Then you could just plot the x-vals and y-vals.
import numpy as np
import matplotlib.pyplot as plt
curve = np.array([1,2,3,4,5])
x = np.linspace(0,10,100)
y = [np.polyval(curve, i) for i in x]
plt.plot(x,y)
A very pythonic solution is to use list comprehension to calculate the values for the function.
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, 10, 11)
coeffs = [1, 2, 3, 4, 5]
y = np.array([np.sum(np.array([coeffs[i]*(j**i) for i in range(len(coeffs))])) for j in x])
plt.plot(x, y)
plt.show()
Generic, vectorized implementation:
from typing import Sequence, Union
import numpy as np
import matplotlib.pyplot as plt
Number = Union[int, float, complex]
def polyval(coefficients: Sequence[Number], x: Sequence[Number]) -> np.ndarray:
# expand dimensions to allow broadcasting (constant time + inexpensive)
# axis=-1 allows for arbitrarily shaped x
x = np.expand_dims(x, axis=-1)
powers = x ** np.arange(len(coefficients))
return powers # coefficients
def polyplot(coefficients: Sequence[Number], x: Sequence[Number]) -> None:
y = polyval(coefficients, x)
plt.plot(x, y)
polyplot(np.array([0, 0, -1]), np.linspace(-10, 10, 210))
plt.show()

Categories