HOWTO · Matplotlib

Traccia un cerchio in Matplotlib

Possiamo tracciare un cerchio usando patch circle, circle equation e scatter plot in Matplotlib.

In questa pagina

Per disegnare un cerchio geometrico in Matplotlib, usa matplotlib.patches.Circle e aggiungi la patch a un oggetto Axes. Puoi anche tracciare un cerchio a partire dalla sua equazione oppure usare un marker scatter per rappresentare rapidamente un simbolo circolare. La patch è in genere la scelta più diretta quando il cerchio deve avere un centro e un raggio espressi nelle coordinate dei dati.

Disegnare un cerchio con matplotlib.patches.Circle

matplotlib.patches.Circle crea una patch specificando un centro (x, y) e un raggio. Aggiungila a un oggetto Axes con add_patch; imposta un rapporto d’aspetto uguale affinché un’unità sull’asse x abbia la stessa lunghezza visiva di un’unità sull’asse y.

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()
ax.add_patch(Circle((2, 1), radius=0.75, fill=False, linewidth=2))
ax.set_aspect("equal", adjustable="box")
ax.set_xlim(0, 4)
ax.set_ylim(-1, 3)
ax.set_title("Circle patch")
plt.show()

Risultato del rendering dell’esempio con la patch Circle: il contorno di un cerchio non riempito, con centro in (2, 1) e raggio 0,75, su assi che vanno da 0 a 4 e da -1 a 3.

Modifica il primo argomento per spostare il centro e radius per ridimensionare il cerchio. Imposta fill=True (il valore predefinito) per riempirlo oppure usa fill=False per mostrarne solo il contorno. Circle è un Artist e può quindi essere aggiunto anche con ax.add_artist(circle). Se esiste già un grafico, plt.gcf().gca().add_artist(circle) aggiunge la patch agli assi correnti della figura corrente; specificare un oggetto Axes è più chiaro quando la figura contiene più grafici.

Se imposti manualmente i limiti degli assi, includi tutta l’estensione del cerchio: per un centro (cx, cy) e un raggio r, l’intervallo x deve comprendere da cx - r a cx + r e l’intervallo y da cy - r a cy + r. Limiti che terminano all’interno di questi intervalli nascondono una parte della patch o della curva basata sull’equazione. Lascia un margine sufficiente anche per mantenere ben visibile il contorno vicino al bordo del grafico.

Disegnare un cerchio a partire dalla sua equazione

Un’equazione parametrica descrive i punti lungo la circonferenza. Per un centro (cx, cy) e un raggio r, usa x = cx + r cos(theta) e y = cy + r sin(theta). Campionando gli angoli da zero a 2π si traccia l’intera curva.

import numpy as np
import matplotlib.pyplot as plt

center_x, center_y = 2, 1
radius = 0.75
theta = np.linspace(0, 2 * np.pi, 200)
x = center_x + radius * np.cos(theta)
y = center_y + radius * np.sin(theta)

fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_aspect("equal", adjustable="box")
ax.set_title("Circle from a parametric equation")
plt.show()

Risultato del rendering dell’esempio parametrico: una curva circolare tracciata dagli angoli campionati, con centro in (2, 1) e raggio 0,75.

In alternativa, l’equazione del cerchio in forma centro-raggio (x - cx)² + (y - cy)² = r² può essere disegnata come una curva di livello zero. Sottrai r**2 dal membro sinistro, valuta il risultato su una griglia e traccia la curva di livello zero. Scegli limiti della griglia che includano tutto il cerchio e mantieni la stessa scala sui due assi; altrimenti la curva visualizzata può apparire deformata.

import numpy as np
import matplotlib.pyplot as plt

center_x, center_y = 2, 1
radius = 0.75
x = np.linspace(center_x - radius - 0.25, center_x + radius + 0.25, 100)
y = np.linspace(center_y - radius - 0.25, center_y + radius + 0.25, 100)
X, Y = np.meshgrid(x, y)
values = (X - center_x) ** 2 + (Y - center_y) ** 2 - radius ** 2

fig, ax = plt.subplots()
ax.contour(X, Y, values, levels=[0])
ax.set_aspect("equal", adjustable="box")
ax.set_title("Circle from the center-radius equation")
plt.show()

Risultato del rendering dell’esempio con curva di livello: la curva di livello zero dell’equazione centro-raggio forma un cerchio con centro in (2, 1) e raggio 0,75.

Disegnare un cerchio con un marker scatter

scatter disegna un marker in corrispondenza di ogni punto dati fornito. L’argomento s imposta l’area del marker in punti tipografici quadrati; è quindi utile per rappresentare un simbolo circolare la cui dimensione visiva rimane legata alla visualizzazione, anziché un cerchio geometrico il cui raggio è misurato nelle coordinate dei dati.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.scatter([2], [1], s=500, marker="o")
ax.set_xlim(0, 4)
ax.set_ylim(-1, 3)
ax.set_aspect("equal", adjustable="box")
ax.set_title("Circular scatter marker")
plt.show()

Risultato del rendering dell’esempio scatter: un singolo marker circolare pieno nel punto (2, 1), la cui dimensione è definita dall’argomento s e non da un raggio nelle coordinate dei dati.

Aumenta o riduci s per modificare l’area visualizzata del marker. Usa una patch Circle quando il raggio deve corrispondere alle distanze sugli assi del grafico; scegli un marker scatter quando vuoi un simbolo di dimensione visiva costante in corrispondenza di un punto dati.

Questa dimensione indipendente dalla scala dei dati è utile per evidenziare punti misurati, indicare un centro o posizionare simboli in grafici che i lettori potrebbero ingrandire. Il marker mantiene le dimensioni in punti tipografici mentre cambia la scala degli assi, quindi la sua dimensione apparente non rappresenta una distanza fissa nei dati del grafico. Scegli una patch o una curva basata sull’equazione quando il cerchio rappresenta un raggio che i lettori devono poter confrontare con altri valori dei dati.

Perché un cerchio può sembrare un’ellisse

Tutti gli esempi precedenti impostano un rapporto d’aspetto uguale con set_aspect("equal", adjustable="box"). Senza questa riga, Matplotlib usa il rapporto d’aspetto automatico: l’oggetto Axes riempie il suo riquadro e, poiché il riquadro è più largo che alto, un’unità sull’asse x viene disegnata più lunga di un’unità sull’asse y. La patch resta un cerchio nelle coordinate dei dati, ma sullo schermo sembra un’ellisse. L’esempio seguente usa lo stesso centro e lo stesso raggio del primo esempio, omettendo solo la riga del rapporto d’aspetto.

import matplotlib.pyplot as plt
from matplotlib.patches import Circle

fig, ax = plt.subplots()
ax.add_patch(Circle((2, 1), radius=0.75, fill=False, linewidth=2))
ax.set_xlim(0, 4)
ax.set_ylim(-1, 3)
ax.set_title("Circle patch without an equal aspect ratio")
plt.show()

La stessa patch Circle senza un rapporto d’aspetto uguale: il cerchio viene allungato in un’ellisse larga perché il riquadro degli assi è più largo che alto.

La correzione consiste nell’aggiungere ax.set_aspect("equal", adjustable="box") prima di impostare i limiti, come negli esempi precedenti. Anche le curve basate su equazioni e le curve di livello si deformano allo stesso modo: senza un rapporto d’aspetto uguale, ogni metodo di questo articolo appare allungato. Con adjustable="box", l’oggetto Axes può restringersi in modo che entrambi gli assi condividano la stessa scala; è il comportamento previsto, non un errore nei dati.