Reputation: 131
I want to plot a few Rectangle outlines using matplotlib. The thing is, I need tons of them, so the "normal" way of drawing rectangles is pretty slow. I solved this using How to speed up plot.... The thing is, I am not able anymore to just plot the edge of the rectangles using fill=None
or edgecolor=...
and facecolor=None
.
See a toy example of my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.patches import Rectangle
def plot_rectangle_from_area(area, color):
"""Plot a rectangle for a given area with color"""
return Rectangle(xy=(area["min_x"], area["min_y"]), width=area["max_x"] - area["min_x"],
height=area["max_y"] - area["min_y"],
fill=None) # linewidth=0, edgecolor=color, facecolor=None, zorder=100, alpha=0,
sample_areas = [{"min_x": -1, "max_x": 0.4, "min_y": 0.7, "max_y": 1},
{"min_x": 0.5, "max_x": 1, "min_y": 0.1, "max_y": 0.5}]
rectangles = []
fig, ax = plt.subplots()
# ... print some contour via meshgrid
if sample_areas:
for area_i in sample_areas:
rectangles.append(plot_rectangle_from_area(area_i, color="r"))
# ... some more cases
# Append the rectangles all at once instead of on their own, see:
# https://stackoverflow.com/questions/33905305/how-to-speed-up-the-plot-of-a-large-number-of-rectangles-with-matplotlib
ax.add_collection(PatchCollection(rectangles))
# ... legend, save, grid, ...
plt.show()
At first I create a array for all the Rectangles, the append to it and use PatchCollection to plot it 1. The following example does exactly the same, just without the PatchCollection and is working fine.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.patches import Rectangle
def plot_rectangle_from_area(area, color):
"""Plot a rectangle from given area"""
return Rectangle(xy=(area["min_x"], area["min_y"]), width=area["max_x"] - area["min_x"],
height=area["max_y"] - area["min_y"],
fill=None) # linewidth=0, edgecolor=color, facecolor=None, zorder=100, alpha=0,
sample_areas = [{"min_x": -1, "max_x": 0.4, "min_y": 0.7, "max_y": 1},
{"min_x": 0.5, "max_x": 1, "min_y": 0.1, "max_y": 0.5}]
fig, ax = plt.subplots()
if sample_areas:
for area_i in sample_areas:
ax.add_patch(plot_rectangle_from_area(area_i, color="r"))
plt.show()
Here are some plots I created with both of these codes. On the left the wished result using the slow method, on the right the result I get with PatchCollection:
I tried multiple combinations of fill, edgecolor, facecolor and even the suggestion with zorder from here.
Is it possible to use the "fast" way of creating rectangles and have just the borders shown?
Upvotes: 2
Views: 1799
Reputation: 14516
Yes - looking at the documentation for PatchCollection, there is a parameter called match_original
, which - when True
- will set the properties of the patches to match those of the original rectangles.
So simply change
ax.add_collection(PatchCollection(rectangles))
to
ax.add_collection(PatchCollection(rectangles, match_original=True))
Upvotes: 2