How to toggle visibility of a subset of patches in an axes - python

I'd like to toggle the visibility of a subset of PolygonPatches in an Axes instance, after adding them as a PatchCollection, but I'm not sure if there's an efficient way to do that.
Is there a way of getting a subset of the patches from the Axes instance, then toggling their visibility?

That is sure possible. You can directly use PatchCollection.set_visible() to show and hide the PatchCollection.
Then, use a Button to toggle visibility.
import numpy as np
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from matplotlib.widgets import Button
import matplotlib.pyplot as plt
patches = []
for i in range(3):
polygon = Polygon(np.random.rand(3, 2), True)
patches.append(polygon)
colors = 100*np.random.rand(len(patches))
p = PatchCollection(patches, alpha=0.4)
p.set_array(np.array(colors))
fig, ax = plt.subplots()
ax.add_collection(p)
bax = fig.add_axes([0.45,0.91,0.1,0.05])
button = Button(bax, "toggle")
def update(event):
p.set_visible(not p.get_visible())
fig.canvas.draw_idle()
button.on_clicked(update)
plt.show()

Related

Matplotlib animation update legend using ArtistAnimation

I want to update the legends in using the ArtistAnimation from Matplotlib.
I try to adapt this solution : Matplotlib animation update title using ArtistAnimation to the legend but it didn't worked. I tried a bunch of others things too but nothing seems to work.
In this case, I got no error, the result is just not what's expected. The legend appears 1 time over 3, only for the green. And the result I want is that the legends change each time with the good color and label.
Here is a minimal example of what I've done :
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
a = np.random.rand(3,3)
fig, ax=plt.subplots()
container = []
colors = ["red","blue","green"]
labels = [0,1,2]
for i in range(a.shape[1]):
line, = ax.plot(a[:,i], color=colors[i])
title = ax.text(0.5,1.05,"Title {}".format(i),
size=plt.rcParams["axes.titlesize"],
ha="center", transform=ax.transAxes, )
legend = ax.legend(handles=[mpl.patches.Patch(color=colors[i], label=labels[i])])
container.append([line, title, legend])
ani = animation.ArtistAnimation(fig, container, interval=750, blit=False)
#ani.save('videos/test.gif')
plt.show()
Here is the result :
This work for me :
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
a = np.random.rand(3,3)
fig, ax=plt.subplots()
container = []
colors = ["red","blue","green"]
labels = [0,1,2]
for i in range(a.shape[1]):
line, = ax.plot(a[:,i], color=colors[i])
title = ax.text(0.5,1.05,"Title {}".format(i),
size=plt.rcParams["axes.titlesize"],
ha="center", transform=ax.transAxes, )
testList = [] # Do an array of the color you want to see
for j in range(len(colors)): # For the example I added all the colors but you can pick only the ones you want
testList.append(mpl.patches.Patch(color=colors[j], label=labels[j]))
legend = ax.legend(handles=testList) # Create the legend
ax.add_artist(legend) # Add manually the legend
container.append([line, title])
ani = animation.ArtistAnimation(fig, container, interval=750, blit=False)
#ani.save('videos/test.gif')
plt.show()
Source :
https://github.com/matplotlib/matplotlib/issues/12833
https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html

Matplotlib issue with grid layout and shapes

Is it possible to create something like the picture? cause I just can't get it to work. Mine isn't showing shapes on the grid for some reason. Any help would be appreciated
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
import matplotlib.patches as mpatches
# Data for plotting
fig, ax = plt.subplots(1,figsize=(8,7))
#use add_patch instead, it's more clear what you are doing
ax.plot([1,5,2],[2,3,4],color="cyan")
rect = Rectangle((5,5),6,6, fill= False)
plt.gca().add_patch(rect)
ax.add_patch(rect)
plt.ylim(1400,2300)
plt.xlim(34,48)
plt.xlabel("inches")
plt.ylabel("weight (lbs)")
plt.title('Váha a vyváženie lietadla Cessna 172N')
plt.legend(["Utility","Normal category"])
plt.grid()
plt.plot
plt.show()

Why are annotations creating white background space around plot?

I wanted to understand why when I annotate the plot it creates a white space around the plot, and how I can remove it.
I have tried the bbox_inches when saving the image and nothing changes. I have tried the subplots_adjust and it adjusts the size of the entire plot around including the white space. I have tried adjusting the margins to no improvement.
import matplotlib as mpl
import matplotlib.pyplot as plt
import plotly as py
from shapely.geometry import Point, Polygon
import geopandas as gpd
import colour
import matplotlib.colors as mcolors
from mpl_toolkits.axes_grid1 import make_axes_locatable
from mpl_toolkits.axes_grid1.colorbar import colorbar
fig1, ax1 = plt.subplots(1, 1)
sm = plt.cm.ScalarMappable(cmap='seismic_r', norm=custom_cmap)
sm.set_array([])
divider1 = make_axes_locatable(ax1)
cax1 = divider1.append_axes("top", size = "5%", pad = "9%")
state2020_data[state2020_data['state'].isin(['ALASKA','HAWAII','DC']) == False].plot(column = 'democrat_margin',
cmap = 'seismic_r', linewidth = 2, edgecolor = '0.2', norm = custom_cmap, ax = ax1)
cb_ax1 = fig1.axes[1]
for idx, row in state2020_data.iterrows():
ax1.annotate(text = row['state_po'], xy = row['coords'],
horizontalalignment = 'center', fontsize = 6)
cb1 = colorbar(sm, cax=cax1, orientation = 'horizontal')
cb_ax1.tick_params(labelsize = 12)
cb_ax1.set_title('Winning margin')
ax1.grid(False)
ax1.axis('tight')
ax1.set_axis_off()
Here is the image if I drop the annotation code:
Here is the image when I include the annotation code:
I'd be really grateful if someone could explain what's going on and how I can erase the additional space.
Thanks

How can I use SymLogNorm with matplotlib but still have colorbar appear linear?

Is there a way to use SymLogNorm with imshow, but make the colorbar basically stretch the colors so that the colorbar actually appears linear?
Below is a short code
from pylab import *
import numpy as np
from matplotlib.colors import SymLogNorm
data = np.random.uniform(low=-10, high=10, size=(10,10))
norm = SymLogNorm(2,vmin=-10,vmax=10)
fig, axes = plt.subplots()
im = axes.imshow(data,extent=[-10,10,-10,10],cmap=plt.cm.jet,norm=norm)
cb = fig.colorbar(im)
that produces this
I basically want this image, but want to stretch the colorbar so the ticks appear linear, not log.

How to fill Pyplot Polygons with a hatch pattern

This is probably ridiculously simple. All I want is to fill a set of Polygons with a hatch pattern, but the pattern never ever appears; I've played with parameters like fill and facecolor without success. The following is a minimal working example
from matplotlib.collections import PatchCollection, LineCollection
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
from matplotlib import rc
region1 = [(0,0),(1,0),(1,1),(0,1)]
region2 = [(1,1),(2,1),(2,2),(1,2)]
polygon1=plt.Polygon(region1,closed=True,fill=False,hatch='/')
polygon2=plt.Polygon(region2,closed=True,fill=False,hatch='\\')
patches = PatchCollection([polygon1,polygon2],match_original=True)
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
ax.add_collection(patches)
ax.relim()
ax.autoscale_view()
plt.show()
Any help is appreciated

Categories

Resources