Matplotlib Line Rotation or Animation - python-3.x

I have created a polar plot and would like to mimic a doppler. This includes a 360 degree sweep around the circle (polar plot). Once the sweep gets to 360 degrees, it needs to go back to zero and continue the sweep.
How do I animate or rotate this line to constantly sweep around this circle? I only want one line to constantly sweep around this plot.
I have looked at several different examples, however, none that create this rotation.
import numpy as np
import math
import matplotlib.pyplot as plt
import pylab
import time
r = 90 * (math.pi/180)
t = 50000
az = 90
el = 5
fig = pylab.figure(figsize = [5.0, 5.0])
ax = fig.gca(projection = 'polar')
fig.canvas.set_window_title('Doppler')
ax.plot(r, t, color ='b', marker = 'o', markersize = '3')
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
currTime = time.time()
prevTime = currTime - 1
deltaTime = currTime - prevTime
outer_border_width = 1
screen_width = 500
screen_height = 500
midpoint = [int(screen_width/2), int(screen_height/2)]
radius = (midpoint[0])
sweep_length = radius - outer_border_width
angle = 50
sweep_interval = 10
sweep_speed = sweep_interval
x = sweep_length * math.sin(angle) + int(screen_width/2)
y = sweep_length * math.cos(angle) + int(screen_height/2)
az = az + ((360.0 / sweep_interval ) * deltaTime)
line1 = (midpoint, [50000, 50000])
#line2 = (midpoint, [20000, 20000])
ax.plot(line1, color = 'b', linewidth = 1)
#Increase the angle by 0.05 radians
angle = angle - sweep_speed
#Reset the angle to 0
if angle > 2 * math.pi:
angle = angle - 2 * math.pi
#ax.plot(line2, color = 'r', linewidth = 1)
#ax.lines.pop(0)
plt.show()
Below is a picture of what it currently looks like for reference:
Many thanks!

I do not understand much of your code, but in order to produce an animation you can use matplotlib.animation.FuncAnimation. Here, you'd give an array of angles to an updating function, which sets the data of the line for each frame.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
r = 90 * (np.pi/180)
t = 50000
fig = plt.figure()
ax = fig.gca(projection = 'polar')
fig.canvas.set_window_title('Doppler')
ax.plot(r, t, color ='b', marker = 'o', markersize = '3')
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_ylim(0,1.02*t)
line1, = ax.plot([0, 0],[0,t], color = 'b', linewidth = 1)
def update(angle):
line1.set_data([angle, angle],[0,t])
return line1,
frames = np.linspace(0,2*np.pi,120)
fig.canvas.draw()
ani = matplotlib.animation.FuncAnimation(fig, update, frames=frames, blit=True, interval=10)
plt.show()

Related

Slider is not updating my diagram correctly

I am trying to plot the biffurcation diagram and its equation.
My problem is that I want to put a slider for when I change the rate in the logistic map equation, but I can't seem to understand what I need to code in the update function.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
rate = np.linspace(1, 4, 1000)
N = 1000
x = np.zeros(N) + 0.5
count = np.arange(round(N*0.9), N)
y = np.zeros(N) + 0.5
#t = 1
# Biffurcation
for rs in range(len(rate)):
for n in range(N-1):
x[n+1] = rate[rs] * x[n] * (1-x[n])
u = np.unique(x[count])
r = rate[rs] * np.ones(len(u))
for i in range(N - 1):
y[i + 1] = rate[rs] * y[i] * (1 - y[i])
# plotting
plt.plot(r, u, '.', markersize=2)
plt.ylabel(ylabel='X')
plt.xlabel(xlabel='r')
plt.title('Biffurcation')
# Plotting
fig, ax = plt.subplots()
axes, = ax.plot(y, 'o-')
ax.set_ylabel(ylabel='X')
ax.set_xlabel(xlabel='Time')
ax.set_title('$x_{n+1}$ = r * $x_{n}$ * (1-$x_{n}$)')
# defining axSlider
fig.subplots_adjust(bottom=0.25)
ax_slider = fig.add_axes([0.15, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, label='r', valmin=1, valmax=4, valinit=1, valstep=rate)
# updating the plot
def update(val):
current_v = slider.val
rate[rs] = current_v
axes.set_ydata(rate[rs])
fig.canvas.draw()
slider.on_changed(update)
plt.show()
I tried to update my plot for when I change the rate on my slider, but it is not working properly.
def update(val):
current_v = slider.val
rate[rs] = current_v
axes.set_ydata(rate[rs])
fig.canvas.draw()

How to plot a contour within a bounded area?

I would like help to plot a counterf only within the region bounded by the blue area in the image, not in the whole graph. I am trying to use matplotlib mpath and mpatches but I am getting several errors.
How could I plot the difference in levels (contorf) only within the area delimited by the blue markings?
Here is my code and the picture
#import base modules
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import LinearNDInterpolator
from matplotlib.collections import PatchCollection
import matplotlib.path as mpath
import matplotlib.patches as mpatches
from mpl_toolkits.axes_grid1 import make_axes_locatable
#Loading the images
img1953 = plt.imread('O1953_9960_A3_1m.tif')
img1999 = plt.imread('O1999_9523_A3_1m.tif')
img2004 = plt.imread('O2004_2385c_A3_1m.tif')
#extract data from surfer files with pandas and name the columns as x and y, first line omited
area = pd.read_csv('diff_analyse_grd.bln', names=['x1', 'y1'], skiprows=1)
slope = pd.read_csv("Abbruchkante.bln", names=['x2', 'y2'], skiprows=1)
crack = pd.read_csv("Anrisskante.bln", names=['x3', 'y3'], skiprows=1)
xmin, xmax = -1100, -200 #set the maximum and miniumum values for the axIs:
ymin, ymax = 1500, 2100
#Read csv from grid/countour file, 1999
grid = np.loadtxt('kr_99_A3_o25.dat', delimiter = ' ', skiprows = 1, usecols = [1,2,3])
x99 = grid[:,0]
y99 = grid[:,1]
z99 = grid[:,2]
#linear space with 600x900 values between min and max graphic values
xi = np.linspace(xmin, xmax, 900)
yi = np.linspace(ymin, ymax, 600)
X, Y = np.meshgrid(xi, yi)
#Using LinearNDInterpolation, year 1999
interpolation99 = LinearNDInterpolator(list(zip(x99, y99)), z99)#https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.LinearNDInterpolator.html
zi99 = interpolation99(X, Y)
#Read csv from grid/countour file, year 1953
grid = np.loadtxt('kr_53_A3_o25.dat', delimiter = ' ', skiprows = 1, usecols = [1,2,3])
x53 = grid[:,0]
y53 = grid[:,1]
z53 = grid[:,2]
#Using LinearNDInterpolation, year 1953
interpolation53 = LinearNDInterpolator(list(zip(x53,y53)), z53)
zi53 = interpolation53(X,Y)
#Calculation of the hight variation:
dh5399 = zi53 - zi99
#Plot graph 1953 - 1999
plt.title('Hangrutschung im Blaubachgraben \n \n Differenz der Geländeoberflachen \n 1953 - 1999')
plt.imshow(img1953,cmap='gray', extent=(xmin, xmax, ymin, ymax))
plt.plot(area.x1,area.y1,'b-', label ='Studienbereich', linewidth = 2)
plt.plot(slope.x2,slope.y2,'r-', label = 'Abbruchkante')
plt.plot(crack.x3,crack.y3,'r--', label = 'Anrisskante')
cs = plt.contour(X,Y,zi99,levels=10, colors='#333')
plt.clabel(cs,inline=True, colors = 'k')
plt.legend(loc='upper right')
plt.xlabel('North [m]')
plt.ylabel('East [m]')
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
cs = plt.contourf(X, Y, dh5399, cmap='rainbow', vmin=-5, vmax=17)
#Setting colorbar right the axis
ax = plt.gca()
divider = make_axes_locatable(ax)
cax = divider.append_axes('right',size='3%',pad=0.1)
cbar = plt.colorbar(cs, cax=cax)
cbar.set_label('\u0394H [m]', rotation = 360, loc = 'top')
plt.tight_layout()
plt.savefig('Dif1.png',dpi=400)
plt.show()

How to adjust color in KDE scatter plot?

I wrote a program to plot oscilloscope data and make a KDE scatter plot with a colorbar. Unfortunately it requires a third party lib (readTrc) as well as the oscilloscope binary file which size is 200MB. The lib can be found on github.
import pandas as pd
import readTrc
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import collections
from scipy.stats import gaussian_kde
trcpath = 'filename.trc' #Binary Oscilloscope File (200 MB)
datX, datY, m = readTrc.readTrc(trcpath)
srx, sry = pd.Series(datX * 1000), pd.Series(datY * 1000)
df = pd.concat([srx, sry], axis = 1)
df.set_index(0, inplace = True)
df = df.abs() #Build Dataframe from above file
fig = plt.figure()
#Eliminate Noise
df[df < 3] = None
df = df.dropna()
#x and y axes data to plot
q1 = np.array(df[1].tolist()[:-2])
q2 = np.array(df[1].tolist()[1:-1])
q3 = np.array(df[1].tolist()[2:])
dq1 = q2 - q1
dq2 = q3 - q2
#Create first Dataset
qqstack = []
xy = np.vstack([dq1,dq2])
#Determine max value for colorbar (highest repeating x/y combination)
df_d = pd.DataFrame([dq1,dq2]).T
for idx, row in df_d.iterrows():
if row[0] == row[1]:
qqstack.append((row[0], row[1]))
cbar_max = collections.Counter(qqstack).most_common(1)[0][-1]
#sort to show most present values last
z = gaussian_kde(xy)(xy)
idx = z.argsort()
x, y, z = dq1[idx], dq2[idx], z[idx]
#plot graph
plt.scatter(x, y,
c=z,
s=20,
cmap = plt.cm.get_cmap('jet'))
#create colormap variable
sm = plt.cm.ScalarMappable(cmap = plt.cm.get_cmap('jet'),
norm = matplotlib.colors.PowerNorm(vmin = -0.1, vmax = cbar_max, gamma = 1))
sm._A = []
fig.colorbar(sm, ticks = range(0, cbar_max, 250))
plt.grid(zorder = 0, alpha = 0.3)
plt.xlabel('dq1 / mV')
plt.ylabel('dq2 / mV')
plt.show()
How can I adjust the color allocation in the plot? I want there to be less blue space so the transition is visible more, like on this graph:

Scaling a PDF to show 100% at peak

I'm displaying a histogram of my data, with an overlaid PDF. My plots all look something like this:
and I'm trying to scale the red curve to show 100% at the peak.
My following toy code is identical to what I'm actually using, apart from the lines in between the two %:
%
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as stats
import numpy as np
my_randoms = np.random.normal(0.5, 1, 50000)
dictOne = {"delta z":my_randoms}
df = pd.DataFrame(dictOne)
df = df[df['delta z'] > -999]
%
fig, ax = plt.subplots()
h, edges, _ = ax.hist(df['delta z'], alpha = 1, density = False, bins = 100)
param = stats.norm.fit(df['delta z'].dropna()) # Fit a normal distribution to the data
pdf_fitted = stats.norm.pdf(df['delta z'], *param)
x = np.linspace(*df['delta z'].agg([min, max]), 100) # x-values
binwidth = np.diff(edges).mean()
ax.plot(x, stats.norm.pdf(x, *param)*h.sum()*binwidth, color = 'r')
# Decorations
graph_title = 'U-B'
plt.grid(which = 'both')
plt.title(r'$\Delta z$ distribution for %s'%graph_title, fontsize = 25)
plt.xlabel(r'$\Delta z = z_{spec} - z_{photo}$', fontsize = 25)
plt.ylabel('Number', fontsize = 25)
plt.xticks(fontsize = 25)
plt.yticks(fontsize = 25)
xmin, xmax = min(df['delta z']), max(df['delta z'])
plt.xlim(xmin, xmax)
plt.annotate(
r'''$\mu_{\Delta z}$ = %.3f
$\sigma_{\Delta z}$ = %.3f'''%(param[0], param[1]),
fontsize = 25, color = 'r', xy=(0.85, 0.85), xycoords='axes fraction')
How would I define another axes object from 0 to 100 on the right-hand side and map the PDF to that?
Or is there a better way to do it?
This is kind of a follow-up to my previous question.
You can use density=True in plotting the histogram.
You use .twinx():
fig = plt.figure(figsize=(10, 8), dpi=72.0)
n_rows = 2
n_cols = 2
ax1 = fig.add_subplot(n_rows, n_cols, 1)
ax2 = fig.add_subplot(n_rows, n_cols, 2)
ax3 = ax1.twinx()
https://matplotlib.org/gallery/api/two_scales.html

facecolor for 3d plot doesn't work

I am new to Python and trying to do a 3d plot and color it with a 4th variable. I use facecolors for this, and for one example below, it doesn't work properly. I have positive value but facecolor only displays negatives. Much appreciate if anybody looks into this.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
from scipy import ndimage
import scipy.ndimage.filters
def RP_source(theta,phi,MT):
x1 = np.sin(theta)*np.cos(phi)
x2 = np.sin(theta)*np.sin(phi)
x3 = np.cos(theta)
#
M11 = MT[0,0]
M22 = MT[1,1]
M33 = MT[2,2]
M12 = MT[0,1]
M23 = MT[1,2]
M13 = MT[0,2]
core = M11*x1*x1 + M22*x2*x2 + M33*x3*x3 + 2*M12*x1*x2 + 2*M13*x1*x3 + 2*M23*x2*x3
## S-wave
# S-wave displacement RP 3-components
us1 = (x1*M11 + x2*M12 + x3*M13) - x1*core
us2 = (x1*M12 + x2*M22 + x3*M23) - x2*core
us3 = (x1*M13 + x2*M23 + x3*M33) - x3*core
# transform S-wave displacement vector to the spherical coordinate (r,theta, phi)
USV = np.cos(theta)*np.cos(phi)*us1 + np.cos(theta)*np.sin(phi)*us2 - np.sin(theta)*us3;
return USV, us1, us2, us3
####################################################################
phi = np.linspace(0., 360., 90) # (degrees) azimuth angle with the x1-axis
theta = np.linspace(0., 180. ,45) #(degrees) angle with x3-axis (assumes positive x3 upward)
# convert to radian
theta = np.radians(theta)
phi = np.radians(phi)
theta, phi = np.meshgrid(theta, phi)
st = np.sin(theta)
ct = np.cos(theta)
sp = np.sin(phi)
cp = np.cos(phi)
# generate the propagation ray vectror
x1 = st*cp
x2 = st*sp
x3 = ct
# define moment-tensor matrix
MT = np.array([[0, 1., 0.],[1., 0., 0.],[0., 0., 0.]])
USV, us1,us2,us3 = RP_source(theta,phi,MT)
#########################
# first plot
scale = np.abs(USV)
x1_sv = scale*x1
x2_sv = scale*x2
x3_sv = scale*x3
fig =plt.figure()
ax1 = fig.gca(projection='3d')
surf1 = ax1.plot_surface(x1_sv,x2_sv,x3_sv,rstride=1, cstride=1, facecolors=cm.jet(USV), alpha=0.6)
plt.ylabel('y-axis')
plt.xlabel('x-axis')
m1 = cm.ScalarMappable(cmap=cm.jet)
m1.set_array(USV)
plt.colorbar(m1)
cm.jet wants a number in the interval [0, 1].
Replace your surf1 =... line with the following line:
surf1 = ax1.plot_surface(x1_sv,x2_sv,x3_sv,rstride=1, cstride=1, facecolors=cm.jet(USV-np.min(USV.ravel())), alpha=0.6)

Resources