Does someone know a free program with which i can draw high quality figures for my scientific thesis. I want to draw similar figures like this example

enter image description here

Picture is from: E. Lucon Oscillateurs coupl ́es, d ́esordre et


Python + Matplotlib (possibly used from within Jupyter Notebooks) can generate that sort of diagram at publication quality and in publication suitable formats, all for free and on multiple platforms.

Some Example Code

As starting point, it's not perfect, but you should be able to get the idea:

Cell 1

%matplotlib inline

Cell 2

import matplotlib.pyplot as plt
from matplotlib.patches import Arc, Arrow
import numpy as np
import itertools

Cell 3

def get_circle(x, y, r=1):
    """ Get a cirlce with a specific position and radius"""
    result = plt.Circle((x, y), r, color='k', fill=False)
    return result

def rpoint(x, y, r, deg):
    """ Get a point on a radius at deg degrees."""
    rang = np.deg2rad(deg)
    x1 = x + r * np.sin(rang)
    y1 = y + r * np.cos(rang)
    return (x1, y1)

def radial(x, y, r=1, ang=0, style="-"):
    """ Draw a radial from a given center to the radius and an angle in degrees."""
    x1, y1 = rpoint(x, y, r, ang)
    result = plt.Line2D([x,x1], [y,y1], color='k', linestyle=style)
    return result

def add_arc(x, y, r=1, ang1=0, ang2=0):
    """ Draw the arrow radius."""
    sr = r * 0.75
    x1, y1 = rpoint(x, y, sr, ang2)
    x2, y2 = rpoint(x, y, sr, ang2+15)
    arc = Arc([x, y], sr*2, sr*2, angle=-100, theta1=ang2, theta2=ang1)
    return arc

def add_arrow(x, y, r=1, ang1=0, ang2=0):
    """ Draw the arrow head."""
    sr = r * 0.75
    x1, y1 = rpoint(x, y, sr, ang2)
    x2, y2 = rpoint(x, y, sr, ang2+10)
    arrow = Arrow(x2, y2, x1-x2, y1-y2, color='k', linewidth=0.25)
    return arrow

def add_lables(x, y, r, ang1, ang2, n):
    """ Add the lables."""
    x1, y1 = rpoint(x, y, r*1.21, ang1)
    x2, y2 = rpoint(x, y, r*1.1, ang2)
    text1 = plt.text(x1, y1, rf'$\theta_{n}$')
    text2 = plt.text(x2, y2, rf'$\omega_{n}$')

def add_item(ax, x, y, rad, n, ang1, ang2, theta_ang):
    """ Add a single item."""
    ax.add_patch(get_circle(x, y, rad))
    ax.add_artist(radial(x, y, rad, ang1))
    ax.add_artist(radial(x, y, rad, ang2, '--'))
    ax.add_patch(add_arc(x, y, rad, ang1, ang2))
    ax.add_patch(add_arrow(x, y, rad, ang1, ang2))

    add_lables(x, y, rad, (ang1+ang2)/2, theta_ang, n)

Cell 4

fig, ax = plt.subplots()

centx, centy = 120, 120
radius = 30
item_rad = 9
item_count = 6
step = 360/item_count
offset = step/2
item_angs = [offset+step*n for n in range(item_count)]
itemxys = [rpoint(centx, centy, radius, item_angs[n]) for n in range(item_count)]
items = [(*p, item_angs[n], n) for n,p in enumerate(itemxys)]

for x, y, ang, n in items:
    add_item(ax, x, y, item_rad, n, 145, 45, ang-offset)

for xy1, xy2 in itertools.combinations(itemxys, 2):
    ax.add_artist(plt.Line2D([xy1[0], xy2[0]], [xy1[1], xy2[1]], color='lightgrey', linestyle=':'))

ax.set_aspect('equal', adjustable='datalim')

Results in:

enter image description here

O.K I haven't varied the angles, the label offsets need more work, etc., but I think this is a good starting point. All of the information I used to get this far was either in the matplotlib manuals or examples.

The above code is available in a GitHub gist: https://gist.github.com/GadgetSteve/557b7c995a824af92f455f5f475948d5

  • I am actually using jupyter notebook but i have no idea how draw such a diagram. Is there some sort of tutorial that explains how to draw such figures in matplotlib?
    – tester931
    Feb 29 '20 at 11:44
  • @Miradius: I have added some example code and a link to a gist. Mar 1 '20 at 15:32
  • Thx Steve! That looks really promising. I will try to workout the little details.
    – tester931
    Mar 2 '20 at 10:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.