Featured

How to Display Figures, Lines, and Arrows with Matplotlib

The matplotlib module can plot geometric figures such as rectangles, circles, and triangles. These figures can then illustrate mathematical, technical, and physical relationships. I’ll now demonstrate the creative options of matplotlib through three examples by illustrating the Pythagorean theorem: a gear representation, a pointer diagram, and a current-carrying conductor in a homogeneous magnetic field.

 

Rectangles

Rectangle objects r are created using the following method:

 

r=patches.Rectangle((x1,y1),b,h,fill,edgecolor,angle)

 

These objects are then inserted into the drawing area via add_patch(r).

 

The x1,y1 tuple defines the lower-left corner of the rectangle. The b and h parameters determine its width and height. The fill parameter is set to True by default and provides the option to fill the rectangle with a specific color: facecolor=color. The edgecolor parameter can be used to change the edge color, and the angle parameter allows the rectangle to be rotated by a specified angle in degrees.

 

Below shows how the Rectangle() function can be used to display three rectangles with predefined dimensions in a drawing area.

 

01 #28_pythagoras.py

02 import numpy as np

03 import matplotlib as mlt

04 import matplotlib.pyplot as plt

05 x1,x2=-3,8

06 y1,y2=-1,11

07 a,b=3,4

08 alpha=np.degrees(np.arctan(b/a))

09 beta=90-np.degrees(np.arctan(a/b))

10 c=np.hypot(a,b)

11 fig,ax=plt.subplots()

12 ax.axis([x1,x2,y1,y2])

13 #(x1,y1),width,height

14 ra=mlt.patches.Rectangle((0,c),a,a,fill=False,lw=2,edgecolor='b', angle=alpha)

15 rb=mlt.patches.Rectangle((c,c),b,b,fill=False,lw=2,edgecolor='b', angle=beta)

16 rc=mlt.patches.Rectangle((0,0),c,c,fill=False,lw=2,edgecolor='b')

17 ax.add_patch(ra)

18 ax.add_patch(rb)

19 ax.add_patch(rc)

20 ax.set_aspect('equal')

21 ax.set_xticks([])

22 ax.set_yticks([])

23 ax.set_frame_on(False)

24 plt.show()

Output

This figure shows how the program above illustrates the Pythagorean theorem.

 

Illustration of the Pythagorean Theorem

Analysis

Lines 05 and 06, together with the axis([x1,x2,y1,y2]) method in line 12, specify the dimensions of the drawing area. In lines 14 to 16, the three rectangle objects ra, rb, and rc are generated using the following method:

 

Rectangle((x1,y1),b,h,fill=False,lw=2,edgecolor='b',angle=…)

 

In this example, the fill parameter is set to False. The edges of the rectangles are drawn in blue due to edgecolor='b'. The rectangle in the upper left is rotated by the angle alpha in the mathematically positive direction (i.e., counterclockwise). The rectangle in the upper right is rotated by the angle beta. The calculations of the angles are performed using the arctan() NumPy function in lines 08 and 09.

 

The add_patch() method in lines 17 to 19 places the rectangles in the drawing area.

 

Circles and Lines

Circle objects (circle) can be created using the following method:

 

kreis=patches.Circle((x,y),radius,fill,lw,edgecolor)

 

These objects can then be embedded into the drawing area via the add_patch(circle) function. In this case, the (x,y) tuple stands for the coordinates of the center of a circle. The third parameter determines the radius.

 

Lines can be created using the plot([x1,x2],[y1,y2]) method you already know. The known properties can be used to change the line styles and widths.

 

Based on the transmission with three gears example, the listing below demonstrates how circles and lines can be displayed using the Circle() and plot() methods. The simplified representation of gears as circles with the mean diameters is used whenever the structures and gear ratios of transmissions must be illustrated.

 

01 #29_transmission.py

02 import matplotlib as mlt

03 import matplotlib.pyplot as plt

04 x1,x2=-12,22

05 y1,y2=-17,12

06 fig,ax=plt.subplots()

07 ax.axis([x1,x2,y1,y2])

08 #(x,y),radius

09 c1=mlt.patches.Circle((-5,5),5,fill=False,lw=2,edgecolor='b')

10 c2=mlt.patches.Circle((-5,-5),5,fill=False,lw=2,edgecolor='b')

11 c3=mlt.patches.Circle((10,-5),10,fill=False,lw=2,edgecolor='b')

12 ax.add_patch(c1)

13 ax.add_patch(c2)

14 ax.add_patch(c3)

15 #x1,x2,y1,y2

16 ax.plot([-5,-5],[-5, 5],lw=1,color='black',ls='-.')

17 ax.plot([-5,10],[-5,-5],lw=1,color='black',ls='-.')

18 ax.plot([-5,10],[5,-5],lw=1,color='black',ls='-.')

19 ax.set_aspect('equal')

20 ax.set_xticks([])

21 ax.set_yticks([])

22 ax.set_frame_on(False)

23 plt.show()

Output

As a result of the program above, three circles and a triangle are output in the drawing area as a technology schema of a transmission, as shown in this figure.

 

Technology Schema of a Transmission

Analysis

The lines of the triangle illustrate the distances between the individual gears. The three circle objects (c1, c2, and c3) are created in lines 09 to 11 using the following method:

 

mlt.patches.Circle((x,y),radius,fill=False,lw=2,edgecolor='b')

 

These lines are embedded in the drawing area in lines 12 to 14 by using the add_patch() method.

 

To change the diameters of the circles for further program tests, then a useful approach is to comment out the statements in lines 20 to 22, while inserting the ax.grid() statement below line 22. In this way, you can better check coordinate changes.

 

The circle.center=(x,y) statement allows you to move the circle object to the desired x,y position. This statement is used in Listing 4.35 for the animation of circular objects.

 

Arrows

Pointer diagrams are needed in AC theory to illustrate the phase shift between voltage and current. The listing below demonstrates how the arrow() method can generate a pointer diagram of arrows for a series circuit consisting of an ohmic resistor and an inductor.

 

01 #30_pointer_diagram.py

02 import matplotlib.pyplot as plt

03 x1,x2=0,12

04 y1,y2=0,8

05 lb=2          #line width

06 pb=0.5        #arrow width

07 pl=1          #arrow length

08 U_R=10        #ohmic voltage drop

09 U_L=5         #inductive voltage drop

10 I=12          #current

11 fig,ax=plt.subplots()

12 ax.axis([x1,x2,y1,y2])

13 #Arrows: x,y,x+dx,y+dy

14 ax.arrow(0,1.8,I,0,color='r',lw=lb,length_includes_head=True,

15           head_width=pb,head_length=pl)

16 ax.arrow(0,2,U_R,0,color='b',lw=lb,length_includes_head=True,

17           head_width=pb,head_length=pl)

18 ax.arrow(U_R,2,0,U_L,color='b',lw=lb,length_includes_head=True,

19           head_width=pb,head_length=pl)

20 ax.arrow(0,2,U_R,U_L,color='b',lw=lb,length_includes_head=True,

21           head_width=pb,head_length=pl)

22 #Labels

23 ax.annotate("$I$",xy=(5,1),xytext=(5,1),fontsize=12)

24 ax.annotate("$U_g$",xy=(5,5),xytext=(5,5.5),fontsize=12)

25 ax.annotate("$U_L$",xy=(10.5,4),xytext=(10.5,4),fontsize=12)

26 ax.annotate("$U_R$",xy=(5,3),xytext=(5,2.5),fontsize=12)

27 ax.set_xticks([])

28 ax.set_yticks([])

29 ax.set_frame_on(False)

30 ax.set_aspect('equal')

31 plt.show()

Output

This figure shows see the output pointer diagram.

 

Pointer Diagram for R-L Series Circuit

Analysis

Arrows can be represented using the following method:

 

arrow(x,y,x+dx,y+dy,color,lw,length_includes_head=True, head_width,head_length)

 

The arrow() method is accessed via the ax object created in line 11. The first two parameters (x and y) define the coordinates of the start of the arrow. The dx and dy parameters determine the direction and length of the arrow. The head_width and head_length properties set the width and length of the arrowhead. An especially important point is that the length_includes_head property must be set to True so that a closed pointer triangle is displayed when rendering.

 

Polygons

A polygon is a plane geometric figure formed by a traverse line. A polygon can be created using the Polygon(xy) constructor of the following class:

 

class matplotlib.patches.Polygon(xy, closed=True, **kwargs)

 

The first parameter (xy) is an array containing the coordinates of the vertices of a polygon. The program below enables you to draw polygons with any number of corners.

 

01 #31_polygon.py

02 import numpy as np

03 import matplotlib.pyplot as plt

04 from matplotlib.patches import Polygon

05 r=10

06 n=6

07 R=1.1*r

08 fig,ax=plt.subplots()

09 ax.axis([-R,R,-R,R])

10 for k in range(n):

11     w=2*np.pi/n

12     x1,y1=r*np.cos(k*w),r*np.sin(k*w)

13     x2,y2=r*np.cos((k+1)*w),r*np.sin((k+1)*w)

14     ax.plot([0,x2],[0,y2],lw=1,color='b')

15     p=Polygon([[x1,y1],[x2,y2]],fill=False,lw=2)

16     ax.add_patch(p)

17 ax.set_aspect('equal')

18 ax.grid(True)

19 plt.show()

Output

This figure shows an example of a polygon drawn using the Polygon method.

 

Hexagon

Analysis

Line 04 imports the patches submodule with the Polygon class. In line 05, you can define the radius r of the perimeter, and in line 06, the number of corners n of the polygon.

 

The most important program actions take place within the for loop (line 10 to 16). Line 11 calculates the angle w of a circle sector (circle section). In lines 12 and 13, the coordinates of the corner points are calculated. The plot() method in line 14 marks the boundaries of the circle sectors. In line 15, the Polygon([[x1,y1],[x2,y2]], ...) constructor of the Polygon class creates the p object. The add_patch(p) method in line 16 adds the p object to the drawing area.

 

You could also have represented a regular polygon much more easily, without a loop construct, using the following statement:

 

p=RegularPolygon((x,y),n,radius=10,fill=False)

ax.add_patch(p)

 

The (x,y) tuple specifies the center of the polynomial. The n and radius parameters define the number of corners and the radius of the polygon. However, the effort of the algorithm for the calculation of the x-y coordinates, which appears complicated at first sight, is justified because it is absolutely necessary in many applications, for example, for the representation of pointers in the complex plane.

 

Usage Example: A Metal Rod in a Magnetic Field

Matplotlib also allows you to create drawings that illustrate physical relationships. The listing below demonstrates how to plot a homogeneous magnetic field with a current-carrying conductor resting on two bus bars.

 

01 #32_mag_field.py

02 import numpy as np

03 import matplotlib as mlt

04 import matplotlib.pyplot as plt

05 x1,x2=0,12

06 y1,y2=0,7

07 x=np.linspace(1,9,9)

08 y=np.linspace(1,6,6)

09 x,y=np.meshgrid(x,y)

10 fig,ax=plt.subplots()

11 ax.axis([x1,x2,y1,y2])

12 rod=mlt.patches.Rectangle((1.4,0.25),0.2,6.5,color='black')#width,height

13 circle=mlt.patches.Circle((10,3.5),0.8,fill=False,lw=2,edgecolor='black')

14 ax.add_patch(circle)

15 ax.add_patch(rod)

16 ax.plot([1,10],[6.5,6.5],lw=2,color='black') #upper line

17 ax.plot([1,10],[0.5,0.5],lw=2,color='black') #bottom line

18 ax.plot([10,10],[0.5,6.5],lw=2,color='black') #right line

19 ax.plot(x,y,marker='x',color='red',ls='none') #magnetic field lines

20 ax.arrow(1.6,3.5,1,0,color='k',lw=2,head_width=0.15)#x,y,x+dx,y+dy

21 ax.arrow(11,6,0,-4.5,color='b',lw=2,head_width=0.16,head_length=0.5)

22 ax.annotate("v",xy=(3,3),xytext=(3,3.4),fontsize=12) #labels

23 ax.annotate("$U_q$",xy=(11.2,3),xytext=(11.3,3.2),fontsize=12)

24 ax.set_xticks([])#no axis labels

25 ax.set_yticks([])#no axis labels

26 ax.set_frame_on(False)

27 ax.set_aspect('equal')

28 plt.show()

Output

Current-Carrying Conductor in a Magnetic Field

Analysis

The figure above shows the top view of a homogeneous magnetic field with two parallel bus bars, a rod of conducting material, and a voltage source. The magnetic field lines are represented by red crosses, which should mean that the magnetic field lines are at right angles to the drawing plane and point in the direction of the drawing plane according to convention.

 

Almost all display elements are known from earlier examples.

 

Editor’s note: This post has been adapted from a section of the book Python for Engineering and Scientific Computing by Veit Steinkamp. Dr. Steinkamp studied electrical engineering and German to become a teacher and pass on his knowledge at vocational schools and technical colleges. He teaches electrical engineering, application development, and mechanical engineering technology. He has also taught theoretical electrical engineering and the fundamentals of electrical engineering.

 

This post was originally published 5/2025.

Recommendation

Python for Engineering and Scientific Computing
Python for Engineering and Scientific Computing

It’s finally here—your guide to Python for engineers and scientists, by an engineer and scientist! Get to know your development environments and the key Python modules you’ll need: NumPy, SymPy, SciPy, Matplotlib, and VPython. Understand basic Python program structures and walk through practical exercises that start simple and increase in complexity as you work your way through the book. With information on statistical calculations, Boolean algebra, and interactive programming with Tkinter, this Python guide belongs on every scientist’s shelf!

Learn More
Rheinwerk Computing
by Rheinwerk Computing

Rheinwerk Computing is an imprint of Rheinwerk Publishing and publishes books by leading experts in the fields of programming, administration, security, analytics, and more.

Comments