How to rotate a 2d plot along the x and y axis - python

I would like to rotate the below example image along the x and y axis, 360 degree. Save the rotated images so that I can create a gif from the saved files.
I used the scipy module with numpy but the output doesn't align with the intended output.
import scipy.misc
from scipy import ndimage
import matplotlib.pyplot as plt
img = cv2.imread('ax2_figure.png')
plt.figure(figsize=(15, 15))
for degree in range(5):
plt.subplot(151+degree)
rotated_img = ndimage.rotate(img, degree*60)
plt.imshow(rotated_img, cmap=plt.cm.gray)
plt.axis('off')
plt.show()
The array that was used to generate the plots.
xy = array([[ 2.56565867, -0.68453676],
[ 2.7705649 , -0.76470133],
[ 1.46815589, -1.31265774],
[-2.70396748, -0.29326683],
[-2.20821359, -0.02249133],
[-2.21705997, -0.18584148],
[ 1.30286825, -1.12362756],
[ 1.33454447, -0.36799136],
[ 0.72123042, -0.19116007],
[ 0.699896 , -0.08678013],
[-2.22643656, 0.70455435],
[-1.86659744, 1.38624018],
[-1.74510161, 1.87923624],
[-1.73131744, 1.49670437],
[-0.01485659, 1.07782199],
[ 0.12371347, 1.53934113],
[ 0.18156564, 1.04662112],
[ 1.20251175, 0.68040644],
[ 1.55150657, 0.36432144],
[ 1.56232503, 0.19121897],
[ 2.07646198, -0.02316096],
[ 1.57910992, -0.26536205]])
fig, ax = plt.subplots()
for start, stop in zip(xy[:-1], xy[1:]):
x, y = zip(start, stop)
ax.plot(x, y, color=uniqueish_color())
plt.show()
example image
output image in gif format.
The image is large about 3MB so I added a link to the image.
image

Related

Logarithmic heatmap in Plotly

I am using heatmap from Plotly. I want to use a logarithmic scale for the color but cannot find how to do so. Here is a MWE:
import plotly.graph_objects as go
import numpy as np
z = [[1e-4,1e-3,1e-2],
[1e-1, 1, 1e1],
[1e2, 1e3, 1e4]]
go.Figure(
data = go.Heatmap(
z = z,
)
).show()
go.Figure(
data = go.Heatmap(
z = np.log(z),
)
).show()
In the MWE I manually calculate the logarithm of the data. I want the color map to be shown as in the second figure but without having to manually transform the data, and also displaying the real z values in the color scale, not the logarithm.
There is an example on the plotly homepage which I adapted to use the viridis colorscale. It's not perfect... you can play with the colorscale denominator to adapt it as you need.
import plotly.graph_objects as go
import plotly.express as px
import numpy as np
viridis = px.colors.sequential.Viridis
z = [[1e-4,1e-3,1e-2],
[1e-1, 1, 1e1],
[1e2, 1e3, 1e4]]
fig1 = go.Figure(
data = go.Heatmap(
z = z,
colorscale = [
[0, viridis[0]],
[1./1000000, viridis[2]],
[1./10000, viridis[4]],
[1./100, viridis[7]],
[1., viridis[9]],
],
colorbar= dict(
tick0= 0,
tickmode= 'array',
tickvals= [0, 1000, 10000]
)
)
)
Another option would be to use:
colorscale = [
[0, viridis[0]],
[1./1000000, viridis[2]],
[1./10000, viridis[4]],
[1./100, viridis[7]],
[1., viridis[9]],
]
px.imshow(z, color_continuous_scale=colorscale, height=600, width=600)
The first one gives you (the second option is rather similar...):

Defining a 2D object and using its area as Boolean

I have defined two space dimesions ( x and z ) and I was able to manually "draw" an object to use it as a boolen for solving an equation. I defined it as it follows:
A = np.zeros((nz,nx))
object = np.ones_like(A)
object[ int(5/dz):int(10/dz) , int(5/dx):int(10/dz) ] = 2
object = object == 2
By doing that I can define an square 5x10 in z dimesion and 5x10 in x dimesion , and apply the algorythim which understands this as an area , I think. But when it comes to draw complex areas it ends up being hard doing it by little squares and rectangles.
So I want to automatize an area generation by mouse clicking and I want to be able to use this area as a boolean.
I was able to draw a polygon using:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon
fig, ax = plt.subplots()
object = np.array(plt.ginput(n=-100,mouse_stop=2))
p = Polygon(object, alpha=0.5)
plt.gca().add_artist(p)
plt.draw()
plt.show()
But this outputs z and x coordinates of the vertices, and I tried to use it as boleean but I could'nt write it so that python uderstands it as the area defined by those points.
Is this problem easy to solve?
If you just want to calculate the area of a general polygon, you can use for example the Shapely python package like this:
import numpy as np
import matplotlib.pyplot as plt
from shapely.ops import Polygon
from matplotlib.patches import Polygon as PltPolygon
# Get the coordinate input
canvas_size = np.array([1, 1])
canvas_lim = np.array([[0, canvas_size[0]], [0, canvas_size[1]]])
fig, ax = plt.subplots()
plt.xlim(canvas_lim[0])
plt.ylim(canvas_lim[1])
ax.set_aspect("equal")
coordinates = np.array(plt.ginput(n=-100, mouse_stop=2))
# Use shapely.ops.Polygon to calculate the area
poly = Polygon(coordinates)
area = poly.area
print("The area is {} units^2".format(area))
# Draw the polygon
p = PltPolygon(coordinates, alpha=0.5)
ax.add_artist(p)
plt.show()
If you definitely need the mask, here's one way to rasterize it using numpy and matplotlib.path. For details see the comments in the code:
import numpy as np
import matplotlib.path as mpltPath
import matplotlib.pyplot as plt
# Define the limits of our polygon
canvas_desired_size = np.array([110, 100])
# The pixel size with which we calculate (number of points to consider)
# The higher this number, the more we have to calculate, but the
# closer the approximation will be
pixel_size = 0.1
# Cacluate the actual size of the canvas
num_pxiels = np.ceil(canvas_desired_size / pixel_size).astype(int)
canvas_actual_size = num_pxiels * pixel_size
# Let's create a grid where each pixel's value is it's position in our 2d image
x_coords = np.linspace(
start=0,
stop=canvas_actual_size[0],
endpoint=False,
num=canvas_desired_size[0] / pixel_size,
)
y_coords = np.linspace(
start=0,
stop=canvas_actual_size[1],
endpoint=False,
num=canvas_desired_size[1] / pixel_size,
)
# Since it makes more sense to check if the middle of the pixel is in the
# polygion, we shift everything with half pixel size
pixel_offset = pixel_size / 2
x_centers = x_coords + pixel_offset
y_centers = y_coords + pixel_offset
xx, yy = np.meshgrid(x_centers, y_centers, indexing="ij")
# Flatten our xx and yy matrixes to an N * 2 array, which contains
# every point in our grid
pixel_centers = np.array(
list(zip(xx.flatten(), yy.flatten())), dtype=np.dtype("float64")
)
# Now prompt for the imput shape
canvas_lim = np.array([[0, canvas_actual_size[0]], [0, canvas_actual_size[1]]])
fig, ax = plt.subplots()
plt.xlim(canvas_lim[0])
plt.ylim(canvas_lim[1])
ax.set_aspect("equal")
shape_points = np.array(plt.ginput(n=-100, mouse_stop=2))
# Create a Path object
shape = mpltPath.Path(shape_points)
# Use Path.contains_points to calculate if each point is
# within our shape
shape_contains = shape.contains_points(pixel_centers)
# Reshape the result to be a matrix again
mask = np.reshape(shape_contains, num_pxiels)
# Calculate area
print(
"The shape area is roughly {} units^2".format(
np.sum(shape_contains) * pixel_size ** 2
)
)
# Show the rasterized shape to confirm it looks correct
plt.imshow(np.transpose(mask), aspect="equal", origin="lower")
plt.xlim([0, num_pxiels[0]])
plt.ylim([0, num_pxiels[1]])
plt.show()
Alternatively, a simpler solution would be using your plot as an image and thresholding it to get a boolean mask. There should be plent of examples of how to do this on google.

Plot a non-square matrix according to the value at that point

I have an 2 dimensional array generated randomly as:-
In [159]:
arr
arr
Out[159]:
array([[ 0.22415888, 0.75510844, 0.30900038, 0.88540865],
[ 0.57742895, 0.17051546, 0.5770795 , 0.92893646],
[ 0.39222077, 0.84292636, 0.92571946, 0.3890262 ],
[ 0.83965826, 0.30913694, 0.24132208, 0.85672481]])
I want to plot the intensity of every point according to the value at that position. For example:- 0.83965826 should show up as much darker at position (3,1) than the 0.22415888 at (0,0). I need to do it using matplotlib, seaborn or any other other python visualization tool
is that what you want?
sns.heatmap(a, annot=True)
Full code:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
a = np.array([[ 0.22415888, 0.75510844, 0.30900038, 0.88540865],
[ 0.57742895, 0.17051546, 0.5770795 , 0.92893646],
[ 0.39222077, 0.84292636, 0.92571946, 0.3890262 ],
[ 0.83965826, 0.30913694, 0.24132208, 0.85672481]])
sns.heatmap(a, annot=True)
plt.show()

matplotlib 2d numpy array

I have created a 2d numpy array as:
for line in finp:
tdos = []
for _ in range(250):
sdata = finp.readline()
tdos.append(sdata.split())
break
tdos = np.array(tdos)
Which results in:
[['-3.463' '0.0000E+00' '0.0000E+00' '0.0000E+00' '0.0000E+00']
['-3.406' '0.0000E+00' '0.0000E+00' '0.0000E+00' '0.0000E+00']
['-3.349' '-0.2076E-29' '-0.3384E-30' '-0.1181E-30' '-0.1926E-31']
...,
['10.594' '0.2089E+02' '0.3886E+02' '0.9742E+03' '0.9664E+03']
['10.651' '0.1943E+02' '0.3915E+02' '0.9753E+03' '0.9687E+03']
['10.708' '0.2133E+02' '0.3670E+02' '0.9765E+03' '0.9708E+03']]
Now, I need to plot $0:$1 and $0:-$2 using matplotlib, so that the in x axis, I will have:
tdata[i][0] (i.e. -3.463, -3.406,-3.349, ..., 10.708)
,and in the yaxis, I will have:
tdata[i][1] (i.e. 0.0000E+00,0.0000E+00,-0.2076E-29,...,0.2133E+02)
How I can define xaxis and yaxis from the numpy array?
Just try the following recipe and see if it is what you want (two image plot methods followed by the same methods but with cropped image):
import matplotlib.pyplot as plt
import numpy as np
X, Y = np.meshgrid(range(100), range(100))
Z = X**2+Y**2
plt.imshow(Z,origin='lower',interpolation='nearest')
plt.show()
plt.pcolormesh(X,Y,Z)
plt.show()
plt.imshow(Z[20:40,30:70],origin='lower',interpolation='nearest')
plt.show()
plt.pcolormesh(X[20:40,30:70],Y[20:40,30:70],Z[20:40,30:70])
plt.show()
, results in:

Matplotlib: Plot movements in 3D

I have a solver that solves a system of equations in 3 variables. Each iteration, it has a new guess on all three variables. The guesses over iterations look like this:
array([[ 0.86063431, 0.07119279, 1.70377142],
[ 0.86391084, 0.07014899, 1.72184785],
[ 0.86332177, 0.069444 , 1.71182579],
[ 0.86192988, 0.06913941, 1.69818289],
[ 0.86166436, 0.06916367, 1.69527615]])
(Here for 5 iterations). I would like to plot these using matplotlib. I was thinking about having a dot for each of these coordinates, and have a line connecting them to show the order of coordinates.
Is this a good way of visualizing this? How would I do that using matplotlib?
You can plot this as a 3D trajectory with matplotlib:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
points = np.array([[ 0.86063431, 0.07119279, 1.70377142],
[ 0.86391084, 0.07014899, 1.72184785],
[ 0.86332177, 0.069444 , 1.71182579],
[ 0.86192988, 0.06913941, 1.69818289],
[ 0.86166436, 0.06916367, 1.69527615]]).T
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.plot(points[0], points[1], points[2], marker = 'x')
ax.scatter(*points.T[0], color = 'red')
plt.show()

Categories

Resources