I have coded a simple script to visualise polygons and to color them according to a given attribute. Everything works fine except that I am not able to specify customised limits for the Colormap (e.g. using vmin and vmax). Any hint? Thanks in advance!
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from pylab import get_cmap
polyg=np.random.rand(4,9)
ap=np.random.rand(4,1)*1e-2
fig = plt.figure()
ax = Axes3D(fig)
cmap = get_cmap('plasma')
dim = polyg.shape
vert = 3
for i in range(0, dim[0]):
x = np.zeros(vert)
y = np.zeros(vert)
z = np.zeros(vert)
for j in range(0, vert):
x[j] = polyg[i, j * 3 ]
y[j] = polyg[i, j * 3 + 1]
z[j] = polyg[i, j * 3 + 2]
verts = [list(zip(x, y, z))]
collection = Poly3DCollection(verts, alpha=0.4)
collection.set_facecolor(cmap(ap[i]))
ax.add_collection3d(collection)
fig.colorbar(collection, ax=ax)
plt.xlabel("X [m]", fontsize=14)
plt.ylabel("Y [m]", fontsize=14)
plt.show()
Related
I can evaluate the value of pi using different data points by Python. But for each repeat I want to plot the scatter plot like this:
My python code for finding pi using monte carlo method is :
from random import *
from math import sqrt
inside=0
n=10**6
for i in range(0,n):
x=random()
y=random()
if sqrt(x*x+y*y)<=1:
inside+=1
pi=4*inside/n
print (pi)
If you get errors about the backend use this:
import matplotlib as mp
mp.use('Tkagg')
Which will set the backend to TkAgg, which uses the Tkinter user interface toolkit.
import numpy as np
import matplotlib.pyplot as plt
n=1e3
x = 1-2*np.random.random(int(n))
y = 1-2.*np.random.random(int(n))
insideX, insideY = x[(x*x+y*y)<=1],y[(x*x+y*y)<=1]
outsideX, outsideY = x[(x*x+y*y)>1],y[(x*x+y*y)>1]
fig, ax = plt.subplots(1)
ax.scatter(insideX, insideY, c='b', alpha=0.8, edgecolor=None)
ax.scatter(outsideX, outsideY, c='r', alpha=0.8, edgecolor=None)
ax.set_aspect('equal')
fig.show()
To further elaborate Robbie's code:
import numpy as np
import matplotlib.pyplot as plt
n = 1000
xy = np.random.uniform(-1, 1, 2 * n).reshape((2, n))
in_marker = xy[0]**2 + xy[1]**2 <= 1
pi = np.sum(in_marker) / n * 4
in_xy = xy[:, in_marker]
out_xy = xy[:, ~in_marker]
fig, ax = plt.subplots(1)
ax.scatter(*in_xy,c='b')
ax.scatter(*out_xy,c='r')
ax.set_aspect('equal')
fig.show()
building from your code, this may get you started:
import matplotlib.pyplot as plt
from random import random
inside = 0
n = 10**3
x_inside = []
y_inside = []
x_outside = []
y_outside = []
for _ in range(n):
x = random()
y = random()
if x**2+y**2 <= 1:
inside += 1
x_inside.append(x)
y_inside.append(y)
else:
x_outside.append(x)
y_outside.append(y)
pi = 4*inside/n
print(pi)
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.scatter(x_inside, y_inside, color='g', marker='s')
ax.scatter(x_outside, y_outside, color='r', marker='s')
fig.show()
although i prefer this answer that uses numpy from the start...
Here is a variation on hiro protagonist's code, using random.uniform() to allow for random numbers between -1.0 and 1.0, allowing all the points to be plotted, and not just 1/4 of it (not the most elegant code, but it is spelled-out to learn the basics of the Monte Carlo Simulation):
import matplotlib.pyplot as plt
import random
inside = 0
n = 10**3
x_inside = []
y_inside = []
x_outside = []
y_outside = []
for _ in range(n):
x = random.uniform(-1.0,1.0)
y = random.uniform(-1.0,1.0)
if x**2+y**2 <= 1:
inside += 1
x_inside.append(x)
y_inside.append(y)
else:
x_outside.append(x)
y_outside.append(y)
To estimate pi, the points in the circle correspond to the area of the circle enclosing it (pi*radius^2) and the total points correspond to the area of the square enclosing it (2*radius)^2. So this translates into:
(points in the circle)/(total points) = (pi*radius^2)/(2*radius)^2
Solving for pi, the equation becomes:
pi=4*(points in the circle)/(total points)
pi = 4*inside/n
print(pi)
Plot the points inside and outside the circle:
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.scatter(x_inside, y_inside, color='g', marker='s')
ax.scatter(x_outside, y_outside, color='r', marker='s')
fig.show()
Plot of points inside and outside the circle
I have a 3d plot made using matplotlib. I now want to fill the vertical space between the drawn line and the x,y axis to highlight the height of the line on the z axis. On a 2d plot this would be done with fill_between but there does not seem to be anything similar for a 3d plot. Can anyone help?
here is my current code
from stravalib import Client
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
... code to get the data ....
mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
zi = alt
x = df['x'].tolist()
y = df['y'].tolist()
ax.plot(x, y, zi, label='line')
ax.legend()
plt.show()
and the current plot
just to be clear I want a vertical fill to the x,y axis intersection NOT this...
You're right. It seems that there is no equivalent in 3D plot for the 2D plot function fill_between. The solution I propose is to convert your data in 3D polygons. Here is the corresponding code:
import math as mt
import matplotlib.pyplot as pl
import numpy as np
import random as rd
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# Parameter (reference height)
h = 0.0
# Code to generate the data
n = 200
alpha = 0.75 * mt.pi
theta = [alpha + 2.0 * mt.pi * (float(k) / float(n)) for k in range(0, n + 1)]
xs = [1.0 * mt.cos(k) for k in theta]
ys = [1.0 * mt.sin(k) for k in theta]
zs = [abs(k - alpha - mt.pi) * rd.random() for k in theta]
# Code to convert data in 3D polygons
v = []
for k in range(0, len(xs) - 1):
x = [xs[k], xs[k+1], xs[k+1], xs[k]]
y = [ys[k], ys[k+1], ys[k+1], ys[k]]
z = [zs[k], zs[k+1], h, h]
#list is necessary in python 3/remove for python 2
v.append(list(zip(x, y, z)))
poly3dCollection = Poly3DCollection(v)
# Code to plot the 3D polygons
fig = pl.figure()
ax = Axes3D(fig)
ax.add_collection3d(poly3dCollection)
ax.set_xlim([min(xs), max(xs)])
ax.set_ylim([min(ys), max(ys)])
ax.set_zlim([min(zs), max(zs)])
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
pl.show()
It produces the following figure:
I hope this will help you.
I have the following (example) code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.jet)
cmap.set_array([])
fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap.to_rgba(i + 1))
fig.colorbar(cmap, ticks=c)
plt.show();
I would like to find a substirute for cmap.to_rgba that makes the colour of each line come out as a differnet shade of blue. Basically I want to keep the same layout as the result of this code, but using the colour map Blues.
How can I do it?
You need to change your colormap that you are using from jet to Blues.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.Blues)
cmap.set_array([])
fig, ax = plt.subplots(dpi=100)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap.to_rgba(i + 1))
fig.colorbar(cmap, ticks=c)
plt.show()
This produces:
I can evaluate the value of pi using different data points by Python. But for each repeat I want to plot the scatter plot like this:
My python code for finding pi using monte carlo method is :
from random import *
from math import sqrt
inside=0
n=10**6
for i in range(0,n):
x=random()
y=random()
if sqrt(x*x+y*y)<=1:
inside+=1
pi=4*inside/n
print (pi)
If you get errors about the backend use this:
import matplotlib as mp
mp.use('Tkagg')
Which will set the backend to TkAgg, which uses the Tkinter user interface toolkit.
import numpy as np
import matplotlib.pyplot as plt
n=1e3
x = 1-2*np.random.random(int(n))
y = 1-2.*np.random.random(int(n))
insideX, insideY = x[(x*x+y*y)<=1],y[(x*x+y*y)<=1]
outsideX, outsideY = x[(x*x+y*y)>1],y[(x*x+y*y)>1]
fig, ax = plt.subplots(1)
ax.scatter(insideX, insideY, c='b', alpha=0.8, edgecolor=None)
ax.scatter(outsideX, outsideY, c='r', alpha=0.8, edgecolor=None)
ax.set_aspect('equal')
fig.show()
To further elaborate Robbie's code:
import numpy as np
import matplotlib.pyplot as plt
n = 1000
xy = np.random.uniform(-1, 1, 2 * n).reshape((2, n))
in_marker = xy[0]**2 + xy[1]**2 <= 1
pi = np.sum(in_marker) / n * 4
in_xy = xy[:, in_marker]
out_xy = xy[:, ~in_marker]
fig, ax = plt.subplots(1)
ax.scatter(*in_xy,c='b')
ax.scatter(*out_xy,c='r')
ax.set_aspect('equal')
fig.show()
building from your code, this may get you started:
import matplotlib.pyplot as plt
from random import random
inside = 0
n = 10**3
x_inside = []
y_inside = []
x_outside = []
y_outside = []
for _ in range(n):
x = random()
y = random()
if x**2+y**2 <= 1:
inside += 1
x_inside.append(x)
y_inside.append(y)
else:
x_outside.append(x)
y_outside.append(y)
pi = 4*inside/n
print(pi)
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.scatter(x_inside, y_inside, color='g', marker='s')
ax.scatter(x_outside, y_outside, color='r', marker='s')
fig.show()
although i prefer this answer that uses numpy from the start...
Here is a variation on hiro protagonist's code, using random.uniform() to allow for random numbers between -1.0 and 1.0, allowing all the points to be plotted, and not just 1/4 of it (not the most elegant code, but it is spelled-out to learn the basics of the Monte Carlo Simulation):
import matplotlib.pyplot as plt
import random
inside = 0
n = 10**3
x_inside = []
y_inside = []
x_outside = []
y_outside = []
for _ in range(n):
x = random.uniform(-1.0,1.0)
y = random.uniform(-1.0,1.0)
if x**2+y**2 <= 1:
inside += 1
x_inside.append(x)
y_inside.append(y)
else:
x_outside.append(x)
y_outside.append(y)
To estimate pi, the points in the circle correspond to the area of the circle enclosing it (pi*radius^2) and the total points correspond to the area of the square enclosing it (2*radius)^2. So this translates into:
(points in the circle)/(total points) = (pi*radius^2)/(2*radius)^2
Solving for pi, the equation becomes:
pi=4*(points in the circle)/(total points)
pi = 4*inside/n
print(pi)
Plot the points inside and outside the circle:
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.scatter(x_inside, y_inside, color='g', marker='s')
ax.scatter(x_outside, y_outside, color='r', marker='s')
fig.show()
Plot of points inside and outside the circle
I wonder if there is a more elegant way to draw the polygon in below code, or with a special plot function or parameter ?
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
x = np.linspace(-4,4,150)
# plot density with shaded area showing Pr(-2 <= x <= 1)
lb = -2
ub = 1
d=norm.pdf(x)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, d)
### can this be done more elegantly ###
sx = np.linespace(lb,ub,100)
sd = norm.pdf(sx)
sx = [lb] + sx + [ub]
sd = [0] + list(sd) + [0]
xy = np.transpose(np.array([sx, sd]))
pgon = plt.Polygon(xy, color='b')
#######################################
ax.add_patch(pgon)
plt.show()
Perhaps you are looking for plt.fill_between:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
x = np.linspace(-4,4,150)
# plot density with shaded area showing Pr(-2 <= x <= 1)
lb = -2
ub = 1
d = norm.pdf(x)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, d)
idx = np.searchsorted(x,[lb,ub])
sx = x[idx[0]:idx[1]]
sd = d[idx[0]:idx[1]]
plt.fill_between(sx, sd, 0, color = 'b')
plt.show()