Use TeX expression "\tanh" in matplotlib legend - python

I'm having some trouble using the TeX "\tanh" expression in my matplotlib chart legend. The reason is that "\t" is also the reserved symbol in Python used for tabs. Hence my expression doesn't show properly. How can I make this work?
This is my code
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10, 1000)
y1 = np.e ** x / (np.e ** x + 1)
y2 = (np.e ** (2 * x) - 1) / (np.e ** (2 * x) + 1)
plt.figure(figsize=(6, 6 / 16 * 9))
ax = plt.gca()
ax.plot(x, y1, color=(0, 101/255, 189/255), linewidth=2, label='$\sigma(x)$')
ax.plot(x, y2, color=(227/255, 114/255, 34/255), linewidth=2, label='$\tanh(x)$')
ax.set_ylim(-1, 1)
ax.set_xlim(-6, 6)
ax.grid(True, which='both', ls='-')
plt.legend()
plt.show()
This is the (wrong) outcome

I believe you need to use a raw-string to ignore the \t, so label=r'$\tanh(x)$'.

Related

How to add colorbars and Titles to the subplots?

How to add colorbars and titles to each each and every plot by using for command just like this picture reference_figure
import numpy as np
import matplotlib.pyplot as plt
import wradlib as wrl
import pyart
import xarray as xr
ds = xr.open_dataset('MDV-20180602-101927-PPIVol.nc')
def sweep(i):
si = ds.sweep_start_ray_index.values
ei = ds.sweep_end_ray_index.values
return slice(si[i],ei[i]+1)
i=0
x = ds.range * np.sin(np.deg2rad(ds.azimuth[sweep(i)]))
y = ds.range * np.cos(np.deg2rad(ds.azimuth[sweep(i)]))
fig, ax = plt.subplots(3, 2, figsize=(12, 15))
ax = ax.flatten()
variables = ['reflectivity',"velocity",'zdr','rhohv','phidp','spectral width']
ref = ax[0].pcolormesh(x/1e3, y/1e3, ds['DBZH'][sweep(i)].T, cmap='pyart_NWSRef')
vel = ax[1].pcolormesh(x/1e3, y/1e3, ds['VELH'][sweep(i)].T, cmap='pyart_NWSVel')
zdr = ax[2].pcolormesh(x/1e3, y/1e3, ds['ZDR'][sweep(i)].T, cmap='pyart_RefDiff', vmin=-1, vmax=8)
rho = ax[3].pcolormesh(x/1e3, y/1e3, ds['RHOHV'][sweep(i)].T, cmap='pyart_RefDiff', vmin=0.5, vmax=1.05)
phidp = ax[4].pcolormesh(x/1e3, y/1e3, ds['PHIDP'][sweep(i)].T, cmap='pyart_Wild25', vmin=-180, vmax=180)
width = ax[5].pcolormesh(x/1e3, y/1e3, ds['WIDTHH'][sweep(i)].T, cmap='pyart_NWS_SPW')
for myax in ax:
[myax.plot(k * np.cos(ds.azimuth[sweep(i)] * np.pi / 180),
k * np.sin(ds.azimuth[sweep(i)] * np.pi / 180), 'k-', linewidth=1, alpha=0.5) for k in [25,75,125]]
myax.set_aspect('equal')
fig.tight_layout()
plt.show()
and the output is
Output
the variables are the titles which should be used
To get the titles you want you just need to iterate through the list within the for loop. So it should look like below for just the variable name. You can do the same thing specifying your other axis labels. Colorbars will work the same way but you will need to use the name for each of your plots.
variables = ['reflectivity',"velocity",'zdr','rhohv','phidp','spectral width']
subplot_= [ref, vel, zdr, rho, phidp, width)
index=0
for myax in ax:
[myax.plot(k * np.cos(ds.azimuth[sweep(i)] * np.pi / 180),
k * np.sin(ds.azimuth[sweep(i)] * np.pi / 180), 'k-', linewidth=1, alpha=0.5) for k in [25,75,125]]
myax.set_aspect('equal')
myax.set_title(variables[index]) #Create a title on the axis
plt.colorbar(subplot_[index],ax=myax)
index+=1 #Add 1

How to fill the area with in Matplotlib [duplicate]

This question already has an answer here:
How to fill space to border with in Matplotlib [duplicate]
(1 answer)
Closed 2 years ago.
I need to fill the area between y1 and y but but I don't understand how to limit the area under y2
import numpy as np
import matplotlib.pyplot as plt
y = lambda z: (4 * z - z ** 2) ** (1 / 2)
y1 = lambda x: (8 * x - x ** 2) ** (1 / 2)
y2 = lambda c: c * 3 ** (1 / 2)
x = np.linspace(0, 12, 500)
z = np.linspace(0, 12, 500)
c = np.linspace(0, 12, 500)
plt.ylim(0, 4)
plt.xlim(0, 4)
plt.plot(z, y(z), color='blue', label="$y=\\sqrt{4x-x^2}$")
plt.plot(c, y2(c), color='black', label='$y=x\\sqrt{3}$')
plt.plot(x, y1(x), color='red', label='$y=\\sqrt{8x-x^2}$')
plt.plot([0, 4], [0, 0], color='yellow', label='y=0')
plt.grid(True, zorder=5)
plt.fill_between(x, y(z), y1(x), where=(y2(c) >= y1(x)), alpha=0.5)
plt.legend()
plt.show()
Do you want to fill between the minimum of y1, y2 and y?
miny = np.minimum(y2(x),y1(x))
plt.fill_between(x, y(x), miny, where=(miny>=y(x)), alpha=0.5)
plt.legend()
plt.show()
Output:

How to automatically set the scale for x-axis to be equal for all subplots in matplotlib?

In this example:
import numpy as np
import matplotlib.pyplot as plt
t1 = np.linspace(0, 1, 1000)
t2 = np.linspace(0, 0.5, 1000)
plt.figure(figsize=(10,5))
plt.subplot(121)
plt.plot(t1, np.sin(t1 * np.pi))
plt.subplot(122)
plt.plot(t2, np.sin(t2 * np.pi))
plt.show()
How can I squeeze the size of the second plot so that the x-axis for both subplots would have the same scale?, so it would look something like this:
I am looking for a simple and automatic way to do this because I have more than 30 subplots and would want them all have the same x-axis scale.
You could approximate the same unit length on both x-axes by specifying the gridspec_kw parameter that defines the ratio of the subplots.
import numpy as np
from matplotlib import pyplot as plt
t1 = np.linspace(0, 1, 1000)
t2 = np.linspace(0, 0.5, 1000)
fig, (ax1, ax2) = plt.subplots(1, 2, gridspec_kw = {"width_ratios": [np.max(t1)-np.min(t1), np.max(t2)-np.min(t2)]})
ax1.plot(t1, np.sin(t1 * np.pi))
ax2.plot(t2, np.sin(t2 * np.pi))
plt.show()
Sample output:
You can use plt.xlim(xmin, xmax) to set the domain of the graph. Using plt.xlim() without giving it parameters returns the current xmin/xmax of the plot. The same applies for plt.ylim().
A presumably not very proper way of doing so but in my opinion useful for a work around would be the use of subplot2grid:
plt.subplot2grid((ROWS, COLS), (START_ROW, START_COL), rowspan=ROWSPAN, colspan=COLSPAN)
using this, you could create two subplots which add up to the desired length and passing the colspan accordingly to the length of your x axis like for example:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 5)
y = np.linspace(0, 10)
plt.figure(figsize=(10,5)) # as specified from your code
# x.max() + y.max() is the total length of your x axis
# this can then be split in the parts of the length x.max() and y.max()
# the parts then should have the correct aspect ratio
ax1 = plt.subplot2grid((1, int(x.max()+y.max()), (0, 0), colspan=int(x.max()))
ax2 = plt.subplot2grid((1, int(x.max()+y.max()), (0, int(x.max())), colspan=int(y.max()))
ax1.plot(x, np.sin(x))
ax2.plot(y, np.sin(y))
plt.show()
The scales seem same for me, you would still have to adjust the xticklabels in case those are supposed to be same as well
You can achieve it by changing the aspect ratio:
import numpy as np
import matplotlib.pyplot as plt
t1 = np.linspace(0, 1, 1000)
t2 = np.linspace(0, 0.5, 1000)
plt.figure(figsize=(10,5))
fig,ax = plt.subplots(nrows = 1,ncols = 2)
ax[0].plot(t1, np.sin(t1 * np.pi))
x1,x2 =ax[1].get_xlim()
x_diff = x2-x1
y1,y2 = ax[1].get_ylim()
y_diff = y2-y1
#plt.subplot(122)
ax[1].plot(t2, np.sin(t2 * np.pi))
ax[1].set_aspect(y_diff/x_diff)
Output:

Looping through subplot which returns function plot in python [duplicate]

This question already has answers here:
How to plot in multiple subplots
(12 answers)
Closed 1 year ago.
I am trying to loop subplot for n rows 2 columns for Gaussian function as shown in following example code. This returns histogram and normal distribution, I tried a couple of methods unsuccessfully, any help is most appreciated.
Speed = [0,10,20,30,40]
Torque1 = []
Torque2 = []
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque1.append(Trq)
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque2.append(Trq)
def gaussian_Histo(s, Title):
mu, sigma = np.mean(s), np.std(s, ddof=1) # mean and standard deviation
fig = plt.figure(Title, figsize=(10, 6), dpi=80)
count, bins, ignored = plt.hist(s, 80, normed=True)
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ), linewidth=2, color='r')
plt.grid(True)
plt.title(Title)
plt.show()
def main():
nrows = 3
fig, axes = plt.subplots(nrows, 2)
for row in axes:
# for i in range(3):
x = gaussian_Histo(Torque1[i], 'Torque at'+str(Speed[i])+'RPM')
y = gaussian_Histo(Torque2[i], 'Torque at'+str(Speed[i])+'RPM')
plot(row, x, y)
plt.show()
def plot(axrow, x, y):
axrow[0].plot(x, color='red')
axrow[1].plot(y, color='green')
main()
The reason you are seeing that error is because you are not returning any value from gaussian_Histo and are therefore trying to plot x = None.
I have removed the part of the code that plots each histogram individually as this will interrupt the plotting of your grid, unless you change the way you are creating that figure. As a result I have used np.histogram rather than plt.hist (plt.hist actually uses np.histogram behind the scenes)
Example:
Speed = [0,10,20,30,40]
Torque1 = []
Torque2 = []
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque1.append(Trq)
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque2.append(Trq)
def gaussian_Histo(s, Title):
mu, sigma = np.mean(s), np.std(s, ddof=1) # mean and standard deviation
count, bins = np.histogram(s, 80, normed=True)
test = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) )
return test
def main():
nrows = 3
fig, axes = plt.subplots(nrows, 2)
for row in axes:
x = gaussian_Histo(Torque1[i], 'Torque at'+str(Speed[i])+'RPM')
y = gaussian_Histo(Torque2[i], 'Torque at'+str(Speed[i])+'RPM')
plot(row, x, y)
plt.show()
def plot(axrow, x, y):
axrow[0].plot(x, color='red')
axrow[1].plot(y, color='green')
main()
This produces the figure:
I came up with code which plots histogram individually. I modified my plotting function (gaussian_Histo) which returns individual plot.
Speed = [0,10,20,30,40]
Torque1 = []
Torque2 = []
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque1.append(Trq)
for i in range(5):
Trq = np.random.normal(0, 10, 5)
Torque2.append(Trq)
# print(Torque1)
def gaussian_Histo(s, Title, ax = None):
mu, sigma = np.mean(s), np.std(s, ddof=1) # mean and standard deviation
if ax is None:
ax = plt.gca()
count, bins, ignored = ax.hist(s, 80, normed=True)
ax.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ), linewidth=2, color='r')
ax.grid(True)
ax.set_title(Title)
plt.show()
for i in range(len(Speed)):
f, (ax1, ax2) = plt.subplots(1, 2, sharey=False, figsize=(8,6), dpi=50)
gaussian_Histo(Torque1[i], 'Torque1 at '+str(Speed[i])+'RPM', ax1)
gaussian_Histo(Torque2[i], 'Torque2 at '+str(Speed[i])+'RPM', ax2)
Individual Plot Results in this link

How to create common colorbar, common labels and title in matplolib using subplots

Hey there I am trying to create a figure with 4 subplots sharing the axes. I was trying for hours to get the right position for a common horizontal colorbar along the x axis. A minimal example of my code is:
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
# Simple data to display in various forms
x = np.linspace(0, 1 * np.pi, 400)
y = np.sin(x ** 2)
z = x+y
fig, axes = plt.subplots(nrows=2, ncols=2, sharex=True, sharey=True)
#print(axes.flat[1])
ax1=axes.flat[0]
ax2=axes.flat[1]
ax3=axes.flat[2]
ax4=axes.flat[3]
scatter = ax1.scatter(x, y, c=z)
ax2.scatter(x, y, c=z)
ax3.scatter(x, 2 * y ** 2 - 1, c=z)
ax4.scatter(x, 2 * y ** 2 - 1, c=z)
#-----------------------------------------#
ax1.set_xlim([0, 1])
ax1.set_ylim([0, 1])
ax2.set_xlim([0, 1])
ax2.set_ylim([0, 1])
ax3.set_xlim([0, 1])
ax3.set_ylim([0, 1])
ax4.set_xlim([0, 1])
ax4.set_ylim([0, 1])
ax1.set(aspect=1, adjustable='box-forced')
ax2.set(aspect=1, adjustable='box-forced')
ax3.set(aspect=1, adjustable='box-forced')
ax4.set(aspect=1, adjustable='box-forced')
ax1.set_ylabel('y')
ax3.set_xlabel('x')
ax3.set_ylabel('y')
ax4.set_xlabel('x')
plt.tight_layout()
cax,kw = mpl.colorbar.make_axes([ax for ax in axes.flat], orientation='horizontal')
plt.colorbar(scatter, cax=cax, **kw)
#-----------------------------------------#
fig.suptitle('Title', fontsize=20.00)
plt.show()
1) My main question: How can I make the beginning of the colorbar aligned with the left end of the x-axis of ax3 and the end of the colorbar aligned with the right edge of the x-axis of ax4?
2) How can I create a common x-label and y-label, which are automatically centered?
Thanks in advance!
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import AxesGrid
import numpy as np
import pylab
# Simple data to display in various forms
x = np.linspace(0, 1 * np.pi, 400)
y = np.sin(x ** 2)
z = x+y
fig = plt.figure()
grid = AxesGrid(fig, 111, # similar to subplot(142)
nrows_ncols=(2, 2),
axes_pad=0.3,
share_all=True,
label_mode="L",
cbar_location="bottom",
cbar_mode="single",
)
scatter = grid[0].scatter(x, y, c=z)
grid[1].scatter(x, y, c=z)
grid[2].scatter(x, 2 * y ** 2 - 1, c=z)
grid[3].scatter(x, 2 * y ** 2 - 1, c=z)
grid.cbar_axes[0].colorbar(scatter)
pylab.figtext(.5, 0.15, 'x')
pylab.figtext(.075, 0.55, 'y', rotation='vertical')
for i in range(4):
grid[i].set_xlim([0, 1])
grid[i].set_ylim([0, 1])
fig.suptitle('Title', fontsize=20.00)
plt.show()
The result of this piece of code is shown below

Categories