Reputation: 33
I have a contour map and I want to make a deformation of all the contour lines, where the contour of level 0.5 will be deformed around the blue point situated in his line and then pass on the blue point on the contour of level 1, and so on.
Original map :
Deformed map :
I think there are two steps, the first one is the delete some parts of the map and the second is to redraw the contour map.
I think i have to iterate through the contour map like this:
CS = plt.contour(X, Y, Z)
for level in CS.collections:
for kp, path in list(enumerate(level.get_paths())):
But I have no idea how to use kp
and path
Any tips for doing this would be appreciated!
Upvotes: 2
Views: 1530
Reputation: 339430
Here is an example on how you could change the contour plot to achieve the intended deformation.
It generates some data x,y,z
which should later be modified. Then it specifies a deformation function, which when multiplied to z
deforms the data in the desired way. This deformation function takes the x
and y
data as input as well as the angle of the line along which to perform the deformation and a width (spread) of the deformation. Finally a parameter i
is used for stearing the degree of deformation (i.e. i=0
means no deformation). Of course you can use any other function to deform your contour.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation
#### generate some x,y,z data ####
r = np.linspace(0,6, num=100)
phi = np.linspace(0, 2*np.pi, num=200)
R, Phi = np.meshgrid(r,phi)
x = R*np.cos(Phi)
y = R*np.sin(Phi)
z = R
##################################
fig, ax=plt.subplots()
ax.set_aspect("equal")
def update(i):
ax.clear()
f = lambda x,y, offs, width, i: 1-i*np.exp(-(np.arctan2(x,y)-offs)**2/width)
z_deformed = z*f(x,y, np.pi/4, 1./8., i=i)
ax.contour(x,y,z_deformed, 10, linewidths=4)
ax.contourf(x,y,z_deformed, 10, alpha=0.3)
ax.set_xlim([-4,4])
ax.set_ylim([-4,4])
update(0) #plot the original data
anipath = 0.5*np.sin(np.linspace(0, np.pi, num=20))**2
ani = matplotlib.animation.FuncAnimation(fig, update, frames=anipath, interval = 100)
plt.show()
Of course you can use other shapes of deformation. E.g. to get a triangular shape use
f = lambda x, A, a, b: A*(1.-np.abs((x-b)/a))*(np.abs((x-b)) < a )
z_deformed = z - f(np.arctan2(x,y), i, 1./8., np.pi/4 )
Upvotes: 2