zoom a part of plot using mpl_toolkits - matplotlib

I created a zoomed portion (in box) of the plot with multiple curves, but the information inside the box is not showing
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes,mark_inset
fig= plt.figure(figsize=(15,10))
ax = plt.axes()
plt.plot(ADB[:300], color = 'darkorange')
plt.plot(ADB1[:300], color = 'green')
plt.plot(ADB2[:300], color = 'red')
plt.plot(ADB3[:300], color = 'darkblue')
plt.legend(fontsize=15)
plt.tick_params(labelsize=18)
axins = zoomed_inset_axes(ax,2,loc='upper right')
x1,x2,y1,y2 = 150,180, 300,400
axins.set_xlim(x1,x2)
axins.set_ylim(y1,y2)
mark_inset(ax,axins,loc1=2,loc2=1)
plt.show()

You also need to plot your data on axins. Take a look at the example provided by matplotlib.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes,mark_inset
fig= plt.figure(figsize=(15,10))
ax = plt.axes()
ax.plot(ADB[:300], color = 'darkorange')
ax.plot(ADB1[:300], color = 'green')
ax.plot(ADB2[:300], color = 'red')
ax.plot(ADB3[:300], color = 'darkblue')
ax.legend(fontsize=15)
ax.tick_params(labelsize=18)
axins = zoomed_inset_axes(ax,2,loc='upper right')
x1,x2,y1,y2 = 150,180, 300,400
axins.set_xlim(x1,x2)
axins.set_ylim(y1,y2)
axins.plot(ADB[:300], color = 'darkorange')
axins.plot(ADB1[:300], color = 'green')
axins.plot(ADB2[:300], color = 'red')
axins.plot(ADB3[:300], color = 'darkblue')
mark_inset(ax,axins,loc1=2,loc2=1)
plt.show()

Related

How to Adjust the color bar height when drawing shape files?

I want to draw geopandas data frame as map. I tried it with the plot function. However, it dose not have shrink like option to change the height of the color bar. Further, using different axis for color bar using divider/ cax not helped. Please help me to shrink the color bar size of the map.
# imports
from osgeo import ogr
import pandas as pd
import geopandas as gpd
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.gridspec import GridSpec
import sys
# create object
fig = plt.figure(figsize=[15,15])
gs = GridSpec(3,3, figure=fig)
# subplots
ax1 = fig.add_subplot(gs[0,0])
ax2 = fig.add_subplot(gs[0,1])
ax3 = fig.add_subplot(gs[1,:])
alba_gdf.plot(column= 'change', ax=ax1, legend=True,
linewidth=0.5, edgecolor='grey')
alba_gdf.plot(column= 'percentage', ax=ax2, legend=True,
linewidth=0.5, edgecolor='grey')
# title
ax1.set_title('A Decade of Population Change \n in Alabama',
fontdict={
'fontsize':'14',
'fontweight': '3'
})
ax2.set_title('A Decade of Percent Population Change \n in Alabama',
fontdict={
'fontsize':'14',
'fontweight':'3'
})
ax3.bar(br1, pop_10, color ='b', width = barWidth,
edgecolor ='grey', label ='population 2010')
ax3.bar(br2, pop_20, color ='g', width = barWidth,
edgecolor ='grey', label ='population 2020')
# Adding Xticks
plt.xlabel('County', fontweight ='bold', fontsize = 15)
plt.ylabel('Population', fontweight ='bold', fontsize = 15)
plt.xticks([r + barWidth for r in range(len(pop_10))],
list(alba_gdf.County_Nam), rotation=90, fontweight=15)
plt.legend()
ax1.set_axis_off()
ax2.set_axis_off()
plt.show()
The map and graph created using above code:

Show exponentiated values along opposite side of log color scale

With a horizontal log-scaled color bar and logged labels along the bottom, is it possible to show the exponentiated (original) values along the top?
So in this example, there should be ticks and labels along the top of the color bar going from mat.min() = 0.058 to mat.max() = 13.396
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
mat = np.exp(np.random.randn(20, 20))
plt.matshow(mat)
norm = mpl.colors.Normalize(1, np.log(mat.max()))
plt.colorbar(plt.cm.ScalarMappable(norm=norm), orientation="horizontal")
plt.savefig("rand_mat.png", dpi=200)
Here is the best answer for your response. I've customized it based on that. Does this result match the intent of your question? The color bar and the size of the figure are not the same, so I adjusted them.
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(20210404)
mat = np.exp(np.random.randn(20, 20))
norm = mpl.colors.Normalize(1, np.log(mat.max()))
fig, (ax, cax) = plt.subplots(nrows=2, gridspec_kw=dict(height_ratios=[15,1],hspace=0.5))
im = ax.matshow(mat)
cbar = plt.colorbar(plt.cm.ScalarMappable(norm=norm), orientation="horizontal", cax=cax)
cax2 = cax.twiny()
cbar.ax.xaxis.set_label_position("bottom")
iticks = np.arange(mat.min(), mat.max(), 2)
cax2.set_xticks(iticks)
ax_pos = ax.get_position()
cax_pos = cbar.ax.get_position()
new_size = [ax_pos.x0, cax_pos.y0, ax_pos.x1 - ax_pos.x0, cax_pos.y1 - cax_pos.y0]
cbar.ax.set_position(new_size)
plt.show()
At the risk of committing a faux pas, I'll answer my own question with the solution that best suits my needs:
cb.ax.secondary_xaxis("top", functions=(np.exp, np.log))
which gives
Full Code
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
mat = np.exp(np.random.randn(20, 20))
plt.matshow(mat)
norm = mpl.colors.Normalize(np.log(mat.min()), np.log(mat.max()))
cb = plt.colorbar(plt.cm.ScalarMappable(norm=norm), orientation="horizontal")
cb_ax_top = cb.ax.secondary_xaxis("top", functions=(np.exp, np.log))
cb_ax_top.set_xticks([0.1, 0.5, 1, 4, 10, 20])

How do I animate a circle to move horizontally?

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
xvalues = np.arange(4000000, 6000000+1000, 1000).tolist()
yvalues = [5000000]*2001
Acc_11 = xvalues
Acc_12 = yvalues
fig = plt.figure(figsize = (5,5))
axes = fig.add_subplot(111)
axes.set_xlim((0, 10000000))
axes.set_ylim((0, 10000000))
point, = plt.Circle((4000000, 5000000), 60000, color = "black")
def ani(coords):
point.set_data([coords[0]],[coords[1]])
return point
def frames():
for acc_11_pos, acc_12_pos in zip(Acc_11, Acc_12):
yield acc_11_pos, acc_12_pos
ani = FuncAnimation(fig, ani, frames=frames, interval=10)
plt.show()
Im getting TypeError: 'Circle' object is not iterable. What I need to do? The size of a circle must be changable and related to axes, so matplotlib circle is the only option (I guess).
Here's a possible solution (assuming you are running in a jupyter notebook cell):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
xvalues = np.arange(4000000, 6000000+1000, 1000).tolist()
yvalues = [5000000]*2001
Acc_11 = xvalues
Acc_12 = yvalues
fig = plt.figure(figsize = (5,5))
axes = fig.add_subplot(111)
axes.set_xlim((0, 10000000))
axes.set_ylim((0, 10000000))
point = plt.Circle((4000000, 5000000), 60000, color = "black")
def init():
point.center = (5, 5)
axes.add_patch(point)
return point,
def ani(i):
point.center = (Acc_11[i],Acc_12[i])
return point
anim = FuncAnimation(fig,
ani,
init_func=init,
frames=200, #len(Acc_11),
interval=10)
HTML(anim.to_html5_video())
You may want to change frames=200 to frames=len(Acc_11) but it will take a while to run.

Matplotlib-Basemap: how to hide the text out of axes?

I want to hide the text outside of the axes, and show only what is inside. I have tried to do it with zorder, but just the text in the axes are gone instead!
import pandas as pd
import numpy as np
import numpy.ma as ma
import matplotlib.pyplot as plt
from matplotlib import cm as CM
from mpl_toolkits.basemap import Basemap
from matplotlib.patches import Polygon
names=['stat','latd', 'longd', 'AQI', 'Grade', 'PM25', 'PM10', 'CO', 'NO2', 'O3', 'O3_8h', 'SO2']
cities=pd.read_table('2013061713.000',sep='\s+',names=names,skiprows=[0],na_values=[9999])
namesa=['LOC1','LOC2','LOC3','LOC4','LOC5','LOC6','LOC7','LOC8']
LOC=pd.read_table('loc/location_use13-06-17.txt',sep='\s+',names=namesa,na_values=[9999])
# Extract the data we're interested in
lat = cities['latd'].values
lon = cities['longd'].values
pm25 = cities['PM25'].values
aqi = cities['AQI'].values
pm25_max=np.nanmax(pm25)
pm25_min=np.nanmin(pm25)
latmax=LOC.iloc[:,:4].max().max()
latmin=LOC.iloc[:,:4].min().min()
lonmax=LOC.iloc[:,4:8].max().max()
lonmin=LOC.iloc[:,4:8].min().min()
llcrnrlon=lonmin-0.5
llcrnrlat=latmin-0.5
urcrnrlon=lonmax+0.5
urcrnrlat=latmax+0.5
fig = plt.figure(figsize=(8, 8))
m = Basemap(llcrnrlon=llcrnrlon,llcrnrlat=llcrnrlat,urcrnrlon=urcrnrlon,urcrnrlat=urcrnrlat, epsg=4269)
m.shadedrelief()
m.drawparallels(np.arange(20.,40,2.5),linewidth=1, dashes=[4, 2], labels=[1,0,0,0], color= 'gray',zorder=0, fontsize=10)
m.drawmeridians(np.arange(100.,125.,2.),linewidth=1, dashes=[4, 2], labels=[0,0,0,1], color= 'gray',zorder=0, fontsize=10)
y_offset = 0.05
rotation = 30
x, y = m(lon, lat)
for i,j,k,a in zip(x[::2],y[::2],pm25[::2],aqi[::2]):
m.scatter(i, j,c=k, s=a, cmap=CM.get_cmap('tab20b',20), alpha=0.5)
plt.text(i, j+y_offset, k,rotation=rotation,fontsize=6,color='w')
for i,j,k,a in zip(x[1::2],y[1::2],pm25[1::2],aqi[1::2]):
m.scatter(i, j,c=k, s=a, cmap=CM.get_cmap('tab20b',20), alpha=0.5)
plt.text(i, j-y_offset, k,rotation=rotation,fontsize=6,color='b')
plt.savefig('PM25_showtext130617.png',dpi=600)
plt.show()
Here is the image with all the text, the text ouside the axes should be hidden:
And this is my current output, when I use the zorder, which is the opposite of what I try to achieve:
plt.text(i, j+y_offset, k,rotation=rotation,fontsize=6,color='w',zorder=-1000)

how can i make my figure made by matplotlib response to a mouse click event?

I read the document of matplotlib and write the following code, it supposed to capture my mouse event and move the grey line position when i clicked. I read this code in jupiter notebook online, it stop to show the coordinate of my cursor as it usually do, What's happend? Can anyone help me?
import pandas as pd
import numpy as np
import matplotlib.colors as mcol
import matplotlib.cm as cm
from scipy import stats
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import scipy.spatial as spatial
np.random.seed(12345)
df = pd.DataFrame([np.random.normal(33500,150000,3650),
np.random.normal(41000,90000,3650),
np.random.normal(41000,120000,3650),
np.random.normal(48000,55000,3650)],
index=[1992,1993,1994,1995])
fig, ax = plt.subplots()
year_avg = df.mean(axis = 1)
year_std = df.std(axis = 1)
yerr = year_std / np.sqrt(df.shape[1]) * stats.t.ppf(1-0.05/2, df.shape[1]-1)
bars=ax.bar(range(df.shape[0]), year_avg, yerr = yerr, color = 'lightslategrey')
threshold=42000
line=plt.axhline(y = threshold, color = 'grey', alpha = 0.5)
cm1 = mcol.LinearSegmentedColormap.from_list("CmapName",["yellow", "orange", "red"])
cpick = cm.ScalarMappable(cmap=cm1)
percentages = []
cpick.set_array([])
def setColor(bars, yerr,threshold):
for bar, yerr_ in zip(bars, yerr):
low = bar.get_height() - yerr_
high = bar.get_height() + yerr_
percentage = (high-threshold)/(high-low)
if percentage>1: percentage = 1
if percentage<0: percentage=0
percentages.append(percentage)
cpick.to_rgba(percentages)
bars = ax.bar(range(df.shape[0]), year_avg, yerr = yerr, color = cpick.to_rgba(percentages))
return bars
line=plt.axhline(threshold, color = 'grey', alpha = 0.5)
setColor(bars, yerr,threshold)
plt.colorbar(cpick, orientation='horizontal')
plt.xticks(range(df.shape[0]), df.index)
fig = plt.figure()
plt.show()
def onclick(event):
print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
('double' if event.dblclick else 'single', event.button,
event.x, event.y, event.xdata, event.ydata))
line.set_ydata(event.ydata)
#plt.draw()
cid = fig.canvas.mpl_connect('button_press_event', onclick)