Testing ipywidgets and Music21¶
These are tests of widgets within Music21
import ipywidgets as widgets
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
@widgets.interact
def f(x=5):
print(x)
interactive(children=(IntSlider(value=5, description='x', max=15, min=-5), Output()), _dom_classes=('widget-in…
@widgets.interact(x=(0, 5))
def ff(x=5):
print(x)
interactive(children=(IntSlider(value=5, description='x', max=5), Output()), _dom_classes=('widget-interact',)…
@widgets.interact_manual(
color=['blue', 'red', 'green'], lw=(1.0, 10.0))
def plot(freq=1.0, color='blue', lw=2, grid=True):
t = np.linspace(-1.0, 1.0, 1000)
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
ax.plot(t, np.sin(2 * np.pi * freq * t),
lw=lw, color=color)
ax.grid(grid)
interactive(children=(FloatSlider(value=1.0, description='freq', max=3.0, min=-1.0), Dropdown(description='col…
freq_slider = widgets.FloatSlider(
value=2.0,
min=1.0,
max=10.0,
step=0.1,
description='Frequency:',
readout_format='.1f',
)
freq_slider
FloatSlider(value=2.0, description='Frequency:', max=10.0, min=1.0, readout_format='.1f')
Create a Custom Widget¶
Older Jupyter provided require/define from RequireJS which gave access to Jupyter widgets. This is no longer the case, so we first need to install anywidget (since it’s not part of the music21 ecosystem):
%pip install anywidget
Requirement already satisfied: anywidget in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (0.9.21)
Requirement already satisfied: ipywidgets>=7.6.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from anywidget) (8.1.5)
Requirement already satisfied: psygnal>=0.8.1 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from anywidget) (0.15.1)
Requirement already satisfied: typing-extensions>=4.2.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from anywidget) (4.12.2)
Requirement already satisfied: comm>=0.1.3 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipywidgets>=7.6.0->anywidget) (0.2.2)
Requirement already satisfied: ipython>=6.1.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipywidgets>=7.6.0->anywidget) (8.29.0)
Requirement already satisfied: traitlets>=4.3.1 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipywidgets>=7.6.0->anywidget) (5.14.3)
Requirement already satisfied: widgetsnbextension~=4.0.12 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipywidgets>=7.6.0->anywidget) (4.0.13)
Requirement already satisfied: jupyterlab-widgets~=3.0.12 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipywidgets>=7.6.0->anywidget) (3.0.13)
Requirement already satisfied: decorator in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (5.1.1)
Requirement already satisfied: jedi>=0.16 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.19.2)
Requirement already satisfied: matplotlib-inline in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.1.7)
Requirement already satisfied: prompt-toolkit<3.1.0,>=3.0.41 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (3.0.48)
Requirement already satisfied: pygments>=2.4.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (2.18.0)
Requirement already satisfied: stack-data in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.6.3)
Requirement already satisfied: pexpect>4.3 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (4.9.0)
Requirement already satisfied: parso<0.9.0,>=0.8.4 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from jedi>=0.16->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.8.4)
Requirement already satisfied: ptyprocess>=0.5 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from pexpect>4.3->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.7.0)
Requirement already satisfied: wcwidth in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from prompt-toolkit<3.1.0,>=3.0.41->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.2.13)
Requirement already satisfied: executing>=1.2.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from stack-data->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (2.1.0)
Requirement already satisfied: asttokens>=2.1.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from stack-data->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (2.4.1)
Requirement already satisfied: pure-eval in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from stack-data->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (0.2.3)
Requirement already satisfied: six>=1.12.0 in /Users/cuthbert/Git/music21base/venv/lib/python3.13/site-packages (from asttokens>=2.1.0->stack-data->ipython>=6.1.0->ipywidgets>=7.6.0->anywidget) (1.16.0)
[1m[[0m[34;49mnotice[0m[1;39;49m][0m[39;49m A new release of pip is available: [0m[31;49m24.3.1[0m[39;49m -> [0m[32;49m25.3[0m
[1m[[0m[34;49mnotice[0m[1;39;49m][0m[39;49m To update, run: [0m[32;49mpip install --upgrade pip[0m
Note: you may need to restart the kernel to use updated packages.
Now create a button that synchronizes Counter value with JS value
import anywidget
import traitlets
class Counter(anywidget.AnyWidget):
_esm = r'''
export function render({ model, el }) {
const bm = document.createElement('button');
bm.textContent = '-';
const bp = document.createElement('button');
bp.textContent = '+';
const span = document.createElement('span');
span.style.marginLeft = '10px';
span.style.marginRight = '10px';
const set_span = () => {
span.textContent = String(model.get('value'));
};
bm.addEventListener('click', () => {
const x = model.get('value');
model.set('value', x - 1);
model.save_changes();
});
bp.addEventListener('click', () => {
const x = model.get('value');
model.set('value', x + 1);
model.save_changes();
});
model.on('change:value', set_span);
el.appendChild(bm);
el.appendChild(span);
el.appendChild(bp);
set_span();
}
'''
value = traitlets.Int(0).tag(sync=True)
c = Counter()
c
<__main__.Counter object at 0x109c752b0>
This number here will change (when reevaluated) with Counter’s value changing above
c.value
4
def a_w(min=0, max=100):
@widgets.interact(x=(min,max))
def f(x=50):
print(x)
a_w(20, 60)
interactive(children=(IntSlider(value=50, description='x', max=60, min=20), Output()), _dom_classes=('widget-i…
def a_w(min=0, max=100):
@widgets.interact(x=(min,max))
def f(x=(min+max)//2):
print(x)
a_w(10, 20)
interactive(children=(IntSlider(value=15, description='x', max=20, min=10), Output()), _dom_classes=('widget-i…