Интерактивный график matplotlib с двумя ползунками

Я использовал matplotlib для создания графика, который зависит от 8 переменных. Я хотел бы изучить, как меняется сюжет, когда я меняю некоторые из них. Я создал какой-то скрипт, который вызывает matplotlib один и генерирует разные снимки, которые потом я конвертирую в фильм, это неплохо, но немного коряво.

  1. Интересно, мог бы я каким-то образом взаимодействовать с регенерацией графика с помощью клавиш клавиатуры, чтобы увеличивать/уменьшать значения некоторых переменных и мгновенно видеть, как меняется график.

  2. Каков наилучший подход для этого?

  3. Также, если вы можете указать мне интересные ссылки или ссылку с примером сюжета всего с двумя ползунками?


person Open the way    schedule 14.07.2011    source источник


Ответы (6)


В дополнение к тому, что упомянул @triplepoint, взгляните на виджет слайдера.

На странице примеров matplotlib есть пример. Это графический ползунок, а не привязка клавиатуры, но он вполне подходит для того, что вы хотите сделать.

Также обратите внимание, что для того, чтобы ползунки и кнопки оставались отзывчивыми и не удалялись сборщиком мусора, ссылки на объекты (amp_slider, freq_slider и т. д.) должны поддерживаться вами самостоятельно.

(Я делаю эту вики для сообщества, так как просто копирую и вставляю пример. Этот конкретный пример учит вредным привычкам (например, from pylab import *), но он передает суть. Пример был исправлено, чтобы избежать использования pylab.)

from numpy import pi, sin
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons

def signal(amp, freq):
    return amp * sin(2 * pi * freq * t)

axis_color = 'lightgoldenrodyellow'

fig = plt.figure()
ax = fig.add_subplot(111)

# Adjust the subplots region to leave some space for the sliders and buttons
fig.subplots_adjust(left=0.25, bottom=0.25)

t = np.arange(0.0, 1.0, 0.001)
amp_0 = 5
freq_0 = 3

# Draw the initial plot
# The 'line' variable is used for modifying the line later
[line] = ax.plot(t, signal(amp_0, freq_0), linewidth=2, color='red')
ax.set_xlim([0, 1])
ax.set_ylim([-10, 10])

# Add two sliders for tweaking the parameters

# Define an axes area and draw a slider in it
amp_slider_ax  = fig.add_axes([0.25, 0.15, 0.65, 0.03], facecolor=axis_color)
amp_slider = Slider(amp_slider_ax, 'Amp', 0.1, 10.0, valinit=amp_0)

# Draw another slider
freq_slider_ax = fig.add_axes([0.25, 0.1, 0.65, 0.03], facecolor=axis_color)
freq_slider = Slider(freq_slider_ax, 'Freq', 0.1, 30.0, valinit=freq_0)

# Define an action for modifying the line when any slider's value changes
def sliders_on_changed(val):
    line.set_ydata(signal(amp_slider.val, freq_slider.val))
    fig.canvas.draw_idle()
amp_slider.on_changed(sliders_on_changed)
freq_slider.on_changed(sliders_on_changed)

# Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
    freq_slider.reset()
    amp_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)

# Add a set of radio buttons for changing color
color_radios_ax = fig.add_axes([0.025, 0.5, 0.15, 0.15], facecolor=axis_color)
color_radios = RadioButtons(color_radios_ax, ('red', 'blue', 'green'), active=0)
def color_radios_on_clicked(label):
    line.set_color(label)
    fig.canvas.draw_idle()
color_radios.on_clicked(color_radios_on_clicked)

plt.show()

Пример

person Community    schedule 14.07.2011
comment
Можно ли на самом деле взаимодействовать с этим инструментом или он просто генерирует изображение? Если да, то что мне нужно для его запуска? В настоящее время я использую IPython - person triplebig; 15.02.2014
comment
@triplebig - Да, это интерактивно. Если при вызове show() ничего не происходит, значит, в вашей установке matplotlib отсутствует интерактивный бэкэнд av. Как вы установили matplotlib? - person Joe Kington; 15.02.2014
comment
@Joe Kington matplotlib поставляется с общей установкой winpython, которую я пытался использовать как на Ipython, так и на Spyder. IPython только что дал мне png, а spyder позволил мне перемещать полосы, но ничего не произошло, когда я это сделал, и он не позволял мне нажимать кнопки - person triplebig; 15.02.2014
comment
@triplebig - По ipython, у вас есть ноутбук ipython? (Вместо обычной оболочки ipython.) Если это так, ноутбуки ipython не могут использовать интерактивный бэкенд. Вам нужно будет запускать вещи либо в обычной оболочке ipython, либо напрямую (например, python name_of_your_file.py). - person Joe Kington; 15.02.2014
comment
@JoeKington Да, по блокноту. Какой интерактивный бэкэнд мне следует искать? Обычно он поставляется со стандартными библиотеками matplotlib? - person triplebig; 15.02.2014
comment
@triplebig - Да, по умолчанию matplotlib будет построен с каким-то интерактивным бэкэндом. Если вы используете готовые двоичные файлы (как в Windows), предположительно человек, который их создал, сделал это правильно. Если вы используете winpython, у matplotlib определенно есть интерактивный бэкенд (вероятно, TkAgg). Попробуйте запустить скрипт напрямую и посмотрите, что произойдет. (т. е. введите python name_of_the_file.py в окне терминала/команды.) - person Joe Kington; 15.02.2014
comment
Чтобы подробнее объяснить, что происходит, заметим, что блокнот ipython — это не то же самое, что ipython. ipython — это интерактивная оболочка Python. Блокнот ipython — это веб-интерфейс, который в основном отправляет фрагменты кода обратно в ipython для оценки и возврата результатов. По этой причине ноутбуки ipython просто отображают цифры matplotlib как статические .png вместо того, чтобы открывать интерактивное окно. Сам ipython (или просто запуск скрипта напрямую с python) покажет интерактивное окно графического интерфейса для каждой фигуры matplotlib. - person Joe Kington; 15.02.2014
comment
Так же, как в демонстрации здесь: matplotlib.org/3.1.1/gallery/widgets/ slider_demo.html ничего не реагирует на клик. - person mLstudent33; 25.02.2020
comment
Пытался запустить серверную часть, но TypeError: interactive() missing 1 required positional argument: 'b' - person mLstudent33; 25.02.2020

Matplotlib имеет довольно приятную функциональность графического интерфейса. Есть несколько примеров документации в исходном архиве matplotlib, в /examples/user_interfaces и matplotlib>/examples/event_handling. В частности, об обработке ключей: http://matplotlib.sourceforge.net/examples/event_handling/keypress_demo.html

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

import numpy as np
import pylab

class plotter:
    def __init__(self, initial_values):
        self.values
        self.fig = pylab.figure()
        pylab.gray()
        self.ax = self.fig.add_subplot(111)
        self.draw()
        self.fig.canvas.mpl_connect('key_press_event',self.key)

    def draw(self):
        im = your_function(self.values)
        pylab.show()
        self.ax.imshow(im)

    def key(self, event):
        if event.key=='right':
            self.values = modify()
        elif event.key == 'left':
            self.values = modify()

        self.draw()
        self.fig.canvas.draw()

Я использовал это, чтобы переключаться между отображением различных изображений в стеке при нажатии клавиш, но вы должны иметь возможность вводить логику для изменения ваших значений при вводе с клавиатуры.

Если вы хотите делать такие вещи, как иметь значения пользовательского ввода, я думаю, что в примерах есть параметры для диалоговых окон, но если вы просто хотите увеличить/уменьшить количество переменных, простое определение пар клавиатуры для них может работать хорошо

person triplepoint217    schedule 14.07.2011

Я последовал совету проверить виджеты в jupyter, и они работают очень хорошо. Пример скрипта загружен на GitHub https://github.com/LeonidBystrykh/course-python-for-beginners/blob/master/Interactive_dots.ipynb

from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import matplotlib.pyplot as plt, random

def series(dots, colr):
    a,b=[],[]
    for i in range(dots):
        a.append(random.randint(1,100))
        b.append(random.randint(1,100))
    plt.scatter(a,b, c=colr)
    return()
interact(series, dots=(1,100,1), colr=["red","orange","brown"]);

Копия изображения ниже

Я могу интерактивно изменить количество точек или их цвет

person Leo    schedule 25.03.2020
comment
Не могли бы вы добавить свой код в виде текста, чтобы он был более полезен другим людям. - person David Buck; 25.03.2020
comment
Очень простой и интуитивно понятный. Спасибо - person Alex Poca; 08.05.2020
comment
Код кажется неполным. Где строки кода, которые создают виджеты? - person mins; 03.11.2020
comment
Виджеты импортируются. Для их использования не требуются дополнительные строки. Вы также можете перейти по ссылке на оригинальный учебник - person Leo; 04.11.2020

Для ноутбуков ipython или jupyter вы можете использовать ipywidgets:

from ipywidgets import *
def update(w=0,h=0):
    print(h+w)

interact(update, w= widgets.IntSlider(value=1, min=0, max=7, step=1) , 
                 h= widgets.IntSlider(value=1, min=0, max=7, step=1) );

См. документацию здесь: https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html

person Alexey Birukov    schedule 12.03.2019

Используйте waitforbuttonpress(timeout=0.001), тогда график увидит, как тикает ваша мышь.

person sema    schedule 13.08.2012

Я не думаю, что простое построение графиков с использованием plt.plot позволит вам это сделать. Вам нужно будет самостоятельно создать собственный скрипт/приложение с графическим интерфейсом, встроив в него Matplotlib. В настоящее время Matplotlib поддерживает все основные инструменты графического интерфейса — PyGTK+, PyQt4 и wxPython.
Я использую wxPython, и встроить в него matplotlib довольно просто. То же самое должно быть и с другими наборами инструментов GUI. Всю необходимую для этого информацию вы можете получить в книге - введите сюда описание изображения

Он доступен на Amazon здесь.

person Pushpak Dagade    schedule 14.07.2011
comment
Если вы хотите сделать это быстро и просто, то метод ползунка внутри matplotlib намного лучше и проще. Просто скопируйте фрагмент и измените несколько вещей. Эта книга тоже хороша, но больше для аванса и если хотите сделать правильно! - person ahelm; 14.07.2011
comment
Немного похоже на рекламу, и ее вклад сомнительный. Это правда, что решение с помощью инструментария GUI возможно, но об этом не просили. - person benni; 14.01.2017