I'm trying use dynamically add rectangles to a plot using Matplotlib but some weird lines are showing up in the plot.
My grid is a class with init and an update function to add new rectangle shapes to the plot
class GridDisplay:
def __init__(self):
# initialize and configure the plot
def UpdatePlotWithIndicesCoords(self, layerID, newData):
# update the plot with a new rectangle
The definition of the functions are shown in the code snippet below
def UpdatePlotWithIndicesCoords(self, layerID, newData):
x0 = newData[0]
x1 = newData[2]
y0 = round(newData[1], 6)
y1 = round(newData[3], 6)
height = round(y1 - y0, 6)
width = round(x1 - x0, 6)
y = y0
x = x0
self.rectangles.append((x, y, width, height))
self.graph.remove()
rectangle = plt.Rectangle((x, y), width, height, edgecolor='yellow', facecolor=layerID, lw=1)
self.ax.add_patch(rectangle)
self.graph = self.ax.plot(self.rectangles)[0]
def __init__(self):
ySize = 15
xSize = 25
xStart = -6
yStart = -6
xEnd = 5
yEnd = 5
self.fig, self.ax = plt.subplots(figsize=(xSize, ySize))
# Set axis limits
self.ax.set_ylim( yStart, yEnd)
self.ax.set_xlim(xStart, xEnd)
# Change major ticks to show every 0.5
self.ax.xaxis.set_major_locator(MultipleLocator(0.5))
self.ax.yaxis.set_major_locator(MultipleLocator(0.5))
# Change minor ticks to show every 0.1
self.ax.xaxis.set_minor_locator(AutoMinorLocator(0.1))
self.ax.yaxis.set_minor_locator(AutoMinorLocator(0.5))
# Turn grid on for both major and minor ticks and style minor slightly
# differently.
self.ax.grid(which='major', color='#CCCCCC', linestyle='--')
self.ax.grid(which='minor', color='#CCCCCC', linestyle=':')
# Set labels and title
self.ax.set_xlabel('h')
self.ax.set_ylabel('v')
self.ax.set_title('S-Cell Routing grid')
# Set grid
self.ax.grid(True)
self.rectangles = []
self.graph = self.ax.plot(self.rectangles)[0]
The UpdatePlotWithIndicesCoords
function is called from another package which simply specifies the bound coordinates of the rectangle (x0, y0, x1, y1) as shown in the snippet below
self.gridDisplay.UpdatePlotWithIndicesCoords(layerID, (startX, startY, endX, endY))
The layerID parameter is used to specify the colour of the rectangle and is not so important to the problem
The image shown is generated from the code below which demonstrates the problem.
import bin.ui.display as GridDisplay
gridDisplay = GridDisplay()
startX = -5
startY = -5
for i in range(1, 6):
layer = str('Metal') + str(i)
newData = (startX + round(i*0.2, 6), startY + round(i*0.5, 6), startX + round(i*0.6, 6), startY + round(i*0.7, 6))
gridDisplay.UpdatePlotWithBoundboxCoords(layer, newData)
I'm not sure what I'm doing wrong but I can't seem to figure out why the random lines are plotted.
I've looked up the documentation and posts on dynamically ploting shapes with Matplotlib but none on the solutions seem to work.
By the way, I also enabled the interactive mode for Matplotlib plt.ion()
Thanks and kind regards.
Update
What worked for me was to change the graph assignment in the last line of code in the UpdatePlotWithIndicesCoords
function from self.graph = self.ax.plot(self.rectangles)[0]
to self.graph = self.ax.add_patch(rectangle)
As explained by @JohanC, the >=4
lines appear because Axes.plot(*args, ...)
is treating the rectangles
(which is a list of 4-tuple elements) as a list of sequences to be plotted. You can visualize it with this minimal reproducible code :
import matplotlib.pyplot as plt
rectangles = [
(-4.8, -4.5, 0.4, 0.2),
(-4.6, -4.0, 0.8, 0.4),
(-4.4, -3.5, 1.2, 0.6),
(-4.2, -3.0, 1.6, 0.8),
(-4.0, -2.5, 2.0, 1.0),
]
plt.plot(rectangles) # gives exactly 4 lines like OP
The solution is to remove the line below and/or assign the graph to the add_patch
call :
self.ax.add_patch(rectangle)
self.graph = self.ax.plot(self.rectangles)[0]
Output (GridDisplayProject> python .\main.py
, including a restart) :