Arrows in Polar Matplotlib Plot - python

I am trying to plot the phasors of the voltage across the resistor, capacitor, and inductor in an series R-L-C circuit. I have done all of the calculations and I can get a decent plot with just the normal ax.plot(theta,r,....).
I would like to make the phasor vectors look like arrows. I have been trying to use ax.arrow(0,0,theta,magnitude) but it looks like a line still. The gist to the code that I have written is here : GIST
My image that I create is
I tried to follow the example that I found on this list because it is very similar to what I want to accomplish, it produces the following image:
When I run their code on my computer I get
I am on Xubuntu 14.04 and running matplotlib 1.3.1. I do see that the example I am using was using matplotlib 0.99 in 2009.
Any help would be much appreciated.

Arrow sizes were too big, this:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
print "matplotlib.__version__ = ", matplotlib.__version__
print "matplotlib.get_backend() = ", matplotlib.get_backend()
# radar green, solid grid lines
plt.rc('grid', color='#316931', linewidth=1, linestyle='-')
plt.rc('xtick', labelsize=15)
plt.rc('ytick', labelsize=15)
# force square figure and square axes looks better for polar, IMO
width, height = matplotlib.rcParams['figure.figsize']
size = min(width, height)
# make a square figure
fig = plt.figure(figsize=(size, size))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, axisbg='#d5de9c')
r = np.arange(0, 3.0, 0.01)
theta = 2*np.pi*r
ax.plot(theta, r, color='#ee8d18', lw=3)
ax.set_rmax(2.0)
plt.grid(True)
ax.set_title("And there was much rejoicing!", fontsize=20)
#This is the line I added:
arr1 = plt.arrow(0, 0.5, 0, 1, alpha = 0.5, width = 0.015,
edgecolor = 'black', facecolor = 'green', lw = 2, zorder = 5)
# arrow at 45 degree
arr2 = plt.arrow(45/180.*np.pi, 0.5, 0, 1, alpha = 0.5, width = 0.015,
edgecolor = 'black', facecolor = 'green', lw = 2, zorder = 5)
plt.show()
Produces:
Better? :)

Related

framing a pie chart in matplotlib

I am desperately trying to add a "dark" border around this pie chart. I have tried the solutions described in plenty of questions here, but none turned out to add anything. You can find part of the attempts in the code:
import matplotlib.pyplot as plt
from cycler import cycler
plt.rc("axes", prop_cycle=cycler("color", ["darkgray", "gray", "lightgray"])
)
plt.rcParams["axes.edgecolor"] = "0.15"
plt.rcParams["axes.linewidth"] = 1.25
labels = ["lab1", "lab2"]
sizes = [2000, 3000]
def make_autopct(values):
def my_autopct(pct):
total = sum(values)
val = int(round(pct*total/100.0))
s = '{p:.2f}%({v:d}%)'.format(p=pct,v=val)
s = f"${val}_{{\\ {pct:.2f}\%}}$"
return s
return my_autopct
fig, ax = plt.subplots(figsize=(10, 3))
ax.pie(sizes, explode=(0,0.02), labels=labels, autopct=make_autopct(sizes))
ax.set_title("title")
ax.patch.set_edgecolor('black')
ax.patch.set_linewidth('1')
plt.savefig("title.png")
If I've understood your question right possible solution is the following:
# pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np
# set chart style
plt.style.use('_mpl-gallery-nogrid')
# set data
x = [5, 2, 3, 4]
# set colors of segments
colors = plt.get_cmap('GnBu')(np.linspace(0.2, 0.7, len(x)))
# plot
fig, ax = plt.subplots()
ax.pie(x, colors=colors, radius=2,
wedgeprops={"linewidth": 2, "edgecolor": "black", 'antialiased': True}, # << HERE
frame=False, startangle=0, autopct='%.1f%%', pctdistance=0.6)
plt.show()
Below, three possibilities:
add a frame around pie patch:
ax.pie(sizes,
explode=(0,0.02),
labels=labels,
autopct=make_autopct(sizes),
frame=True)
add a border using axes coordinates (0, 0) to (1, 1) with fig.add_artist which draw on the fig object:
rect = pt.Rectangle((-0.1, -0.1), 1.2, 1.2,
fill=False, color="blue", lw=3, zorder=-1
transform=ax.transAxes)
fig.add_artist(rect)
add a border using fig coordinates (0, 0) to (1, 1) with fig.add_artist which draw on the fig object:
rect = pt.Rectangle((0.05, 0.05), .9, .9,
fill=False, ec="red", lw=1, zorder=-1,
transform=fig.transFigure)
fig.add_artist(rect)
Result:
Edit This matplotlib's transformations page explains the different coordinate systems

Modifying saved plot with matplotlib

I am having a problem right now. I have run an extremely heavy simulation and, thus, generated a plot with matplotlib containing the results and saved it (as .jpg). However, there are some elemnts of the plot I would like to change, such as labels size and one vertical line. Is there a straighforward way to do this using matplotlib? I know I could have stored the data and now just replot changing the parameters (and, actually, I have done this), but I was wondering whether there is an easier way. Maybe something like:
fig, ax = plt.figure(path_to_figure)
ax.set_ylabel("Y_label")
...
You can refer to below example, which gives you more idea on how you can do this while plotting everything.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
%matplotlib inline
plt.rc('text', usetex=True)
def f(t):
return t ** 2
t1 = np.arange(0.0, 2.0, 0.1)
noise = np.random.randn(len(t1)) * 0.04
# x coordinates for the lines
xcoords = [0.1, 0.3, 0.5]
# colors for the lines
colors = ['r','k','b']
fig = plt.figure(figsize=(4, 3), dpi=200)
ax = fig.add_subplot(1, 1, 1)
plt.scatter(t1, f(t1 + noise), color = 'hotpink', label='Values obtained by experiment', edgecolors='k')
plt.plot(t1, f(t1), ls='solid', label='Theoretical expectation', color='b')
plt.title(r'This is latex title example $\mathbf{E = m \times c^2}$', fontsize='small')
for xc,c in zip(xcoords,colors):
plt.axvline(x=xc, label='line at x = {}'.format(xc), c=c)
plt.grid()
plt.legend(loc=0)
If you want to make all the fonts bold, you can also use below code to make everything bold:
font = {'weight' : 'bold',
'size' : 14 }
plt.rc('font', **font)
def f(t):
return t ** 2
t1 = np.arange(0.0, 2.0, 0.1)
noise = np.random.randn(len(t1)) * 0.04
# x coordinates for the lines
xcoords = [0.1, 0.3, 0.5]
# colors for the lines
colors = ['r','k','b']
fig = plt.figure(figsize=(4, 3), dpi=200)
ax = fig.add_subplot(1, 1, 1)
plt.scatter(t1, f(t1 + noise), color = 'hotpink', label='Values obtained by experiment', edgecolors='k')
plt.plot(t1, f(t1), ls='solid', label='Theoretical expectation', color='b')
plt.title(r'This is latex title example $\mathbf{E = m \times c^2}$', fontsize='small')
plt.xlabel("This is X-label.", fontsize=12)
plt.ylabel("This is Y-label.", fontsize=16)
for xc,c in zip(xcoords,colors):
plt.axvline(x=xc, label='line at x = {}'.format(xc), c=c)
plt.grid()
plt.legend(loc=(1.15,0.2))

How to create a double headed arrow in matplotlib (with text) [duplicate]

I would like to make a simple arrow and a two head arrow. I used the following to make a simple arrow, but I doubt this is the easiest method :
import matplotlib.pyplot as plt
arr_width = .009 # I don't know what unit it is here.
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(range(10))
ax1.arrow(1, 1, 0, .5, width = arr_width, head_width = 3 * arr_width,
head_length = 9 * arr_width)
plt.show()
I can't find how to make two head arrows with this method.
You can create a double-headed arrow using the annotate method with blank text annotation and setting the arrowprops dict to include arrowstyle='<->' as shown below:
import matplotlib.pyplot as plt
plt.annotate(s='', xy=(1,1), xytext=(0,0), arrowprops=dict(arrowstyle='<->'))
plt.show()
You can create double-headed arrows by plotting two plt.arrow which are overlapping. The code below helps to do that.
import matplotlib.pyplot as plt
plt.figure(figsize=(12,6))
# red arrow
plt.arrow(0.15, 0.5, 0.75, 0, head_width=0.05, head_length=0.03, linewidth=4, color='r', length_includes_head=True)
# green arrow
plt.arrow(0.85, 0.5, -0.70, 0, head_width=0.05, head_length=0.03, linewidth=4, color='g', length_includes_head=True)
plt.show()
And the result is like this:
You can see that the red arrow is being plotted firstly, and then the green one. When you supply the correct coordinates, it looks like a double-headed.
You can use matplotlib.patches.FancyArrowPatch to draw a two-headed arrow. This class allows to specify arrowstyle:
import matplotlib.patches as patches
p1 = patches.FancyArrowPatch((0, 0), (1, 1), arrowstyle='<->', mutation_scale=20)
p2 = patches.FancyArrowPatch((1, 0), (0, 1), arrowstyle='<|-|>', mutation_scale=20)
This produces the following arrows:
You can draw two one-headed arrows along the same line but in opposite directions.
import matplotlib.pyplot as plt
# Arrows
plt.arrow(0.3, 0.1, 0.4, 0.7, color='red', head_length = 0.07, head_width = 0.025, length_includes_head = True)
plt.arrow(0.7, 0.8, -0.4, -0.7, color='red', head_length = 0.07, head_width = 0.025, length_includes_head = True)
plt.show()

update bar chart using a slider in matplotlib

I try to make a simple bar chart, where I can monitor a chemical reaction ( A -> B) using a slider for reaction steps.
So far, the following code yields a bar chart for A with a slider for reactionsteps. The print function prints the expected values for A after certain reaction steps. However, the plot won't be updated. I tried plt.draw(), plt.show() and fig.canvas.draw() but none of them worked.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import Slider, Button
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
fig.canvas.set_window_title('Einfluss der Geschwindigkeitskonstanten')
a0 = 1
b0 = 0
plt.axis([0, 5, 0, 2])
plt.xticks([1, 4], ['A', 'B'])
plt.bar(1, a0, color = 'red')
#slider:
axcolor = 'lightblue'
axrs = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
srs = Slider(axrs, 'RS', 0, 20, valinit=0)
def slider_val_fkt(t):
ya = []
t = srs.val
ya = [np.exp(-0.6 * t)]
print(ya)
plt.bar(1, ya, color = 'red')
#plt.draw()
#plt.show()
fig.canvas.draw()
srs.on_changed(slider_val_fkt)
plt.show()
The new bar is drawn inside the slider axes instead of the original axes:
To overcome this you should work on the axes objects instead of using pyplot. However, since you anyways want to update the bar instead of drawing a new one, it is sufficient here to work with the bars themselves and update them using set_height.
bars = plt.bar(1, a0, color = 'red')
axrs = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor='lightblue')
srs = Slider(axrs, 'RS', 0, 20, valinit=0)
def slider_val_fkt(t):
t = srs.val
ya = [np.exp(-0.6 * t)]
bars[0].set_height(ya[0])
fig.canvas.draw_idle()
srs.on_changed(slider_val_fkt)

Change colour scale increments in Python

I have created a frequency time spectrogram plot seen below.
I want to edit the colour scale so that the higher frequencies shown from 20 seconds are more prominent. I think having smaller increments at the lower end of the colour scale (blues) would achieve this but am not sure how to do it. Any help would be great!
Here is what I have so far:
import numpy as np
import matplotlib.pyplot as plt
from obspy.core import read
from obspy.signal.tf_misfit import cwt
import pylab
tr = read("whole.sac")[0]
npts = tr.stats.npts
dt = tr.stats.delta
t = np.linspace(0, dt * npts, npts)
f_min = 1
f_max = 10
scalogram = cwt(tr.data, dt, 8, f_min, f_max)
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.1, 0.7, 0.60])
ax2 = fig.add_axes([0.1, 0.75, 0.75, 0.2])
ax3 = fig.add_axes([0.83, 0.1, 0.03, 0.6])
img = ax1.imshow(np.abs(scalogram)[-1::-1], extent=[t[0], t[-1], f_min, f_max],
aspect='auto', interpolation="nearest")
ax1.set_xlabel("Time after %s [s]" % tr.stats.starttime)
ax1.set_ylabel("Frequency [Hz]")
ax1.set_yscale('linear')
ax2.plot(t, tr.data, 'k')
pylab.xlim([30,72])
fig.colorbar(img, cax=ax3)
plt.show()
You could try other colormaps or make you own according to this recipe.
Or you may want to filter the data to set all values above a given threshold (e.g. 60) to the threshold value. This would use the entire range of the colormap on the range of interest. You can easily use np.clip() to do this.
So...
np.abs(scalogram)[-1::-1]
becomes
np.clip(np.abs(scalogram)[-1::-1], 0, 100)
to clip between 0 and 100.

Categories