Python Matplotlib - зона заполнения между двумя концентрическими окружностями - PullRequest
0 голосов
/ 27 декабря 2018

Я рисую следующий график, используя Matplotlib:

import matplotlib.pyplot as mlp
import numpy.linalg as npl

def ploteig(self, erg:bool) -> None:

    theta = np.arange(start=0, stop=2.0*np.pi, step=0.01)
    r = np.ones(len(theta))

    values, _ = npl.eig(self._p)
    values = values.astype(complex)

    x_unit_circle = r * np.cos(theta)
    y_unit_circle = r * np.sin(theta)

    x_eigenvalues = np.unique(np.append(values, np.complex(1.0)))
    y_eigenvalues = np.zeros(len(x_eigenvalues))

    has_slem = False

    if erg:
        values_abs = np.sort(np.abs(values))
        values_ct1 = np.isclose(values_abs, 1.0)
        if not np.all(values_ct1):
            mu = values_abs[~values_ct1][-1]
            if not np.isclose(mu, 0.0):
                r *= mu;
                x_slem_circle = r * np.cos(theta)
                y_slem_circle = r * np.sin(theta)
                has_slem = True

    fig, ax = mlp.subplots()
    ax.plot(x_unit_circle, y_unit_circle, color='red', linestyle='-', linewidth=3)
    ax.plot(x_eigenvalues, y_eigenvalues, color='blue', linestyle='None', marker='*', markersize=10)

    if has_slem:
        ax.plot(x_slem_circle, y_slem_circle, color='red', linestyle='--', linewidth=1)

    ax.grid(True)
    ax.set_aspect('equal', 'datalim')

    mlp.show()

Если has_slem равно True, то круг Слеми всегда меньше единичного круга, поэтому на графике получается дваконцентрические круги, где внешний круг обозначен (x_unit_circle,y_unit_circle), а внутренний круг - (x_slem_circle,y_slem_circle).

Я хотел бы заполнить область между двумя кружками светло-красным цветом.Это то, что я пробовал до сих пор:

if has_slem:
    ax.plot(x_slem_circle, y_slem_circle, color='red', linestyle='--', linewidth=1)
    ax.fill_between(x_unit_circle, y_unit_circle, -y_unit_circle, color="red", alpha=0.2)
    ax.fill_between(x_slem_circle, y_slem_circle, -y_slem_circle, color="white")

Но у этого подхода есть две проблемы:

  1. Если цвет осей изменится, второй вызов fill_between выдаст неправильныйЗаливка основана на white цвете.
  2. Заливная область выглядит немного смещенной относительно внутреннего круга (есть небольшой белый зазор), как вы можете видеть на скриншоте ниже.

Plot

Итак, вот мой вопрос: есть ли лучший и более точный подход для заполнения области между двумя кругами, который позволяет мне обойти обе проблемы?

На совершенно не связанной ноте: нормально ли вызывать mlp.show() внутри функции?Я не знаю, какие здесь лучшие практики ... может быть, лучше вернуть дескриптор фигуры и позволить потребителю решить, когда его всплыть?

1 Ответ

0 голосов
/ 27 декабря 2018

pyplot.contourf - это то, что вы ищете.Что-то, что может выглядеть следующим образом:

# inner radius
inner = 0.5

# the two circles
thetas = np.linspace(0,2*np.pi, 200)
# you don't need r = np.one(len(thetas))
x_unit_circle = np.cos(thetas)
y_unit_circle = np.sin(thetas)

x_eigens = x_unit_circle * inner
y_eigens = y_unit_circle * inner

xs = np.linspace(-1.1,1.1, 201)
ys = np.linspace(-1.1,1.1, 201)

# mesh for contours
xv,yv = np.meshgrid(xs,ys)

# generate the level map
r = xv**2 + yv**2

pyplot.figure(figsize=(8,8))

# plot the contours with two levels only
# notice the xv, yv parameters
pyplot.contourf(xv, yv, r, levels=[inner**2,1], colors=('r','g','b'))

# plot the two circles
pyplot.plot(x_unit_circle, y_unit_circle, color='b', linewidth=3)
pyplot.plot(x_eigens, y_eigens, color='g', linewidth=3, linestyle='--')

pyplot.show()

и приводить к другому фону: enter image description here

...