Skip to content

Commit

Permalink
Fix #6: Add Jupyter notebook support
Browse files Browse the repository at this point in the history
  • Loading branch information
dubreuia committed Sep 12, 2020
1 parent ca38762 commit d49c5bb
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 99 deletions.
11 changes: 7 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
# vim swap files
# Vim swap files
.gitignore.swp

# idea files
# JetBrains IDEA files
.idea/*

# python setuptools files
# Python setuptools files
build/
dist/
Visual_MIDI.egg-info/
__pycache__

# output plot files
# Output plot files
output

# Jupyther notebook
.ipynb_checkpoints/
46 changes: 43 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,65 @@ Might work with older versions but wasn't tested:

## Usage

Use the `Preset` object to customize the appearance (height, width, colors, etc.) of the plot, and the `Plotter` object to change the render view (number of bars to show, pitch range, etc.). The resulting plot still has all its bars (in this example, 16 bars), but the plot is "zoomed in" to the desired number of bars (int this example, 8 bas). You can still drag and zoom the plot.

- `Plotter#save` - Saves the pretty midi object as a plot file (html) in the provided file
- `Plotter#show` - Shows the pretty midi object as a plot file (html) in the browser
- `Plotter#show_notebook` - Shows the pretty midi object as a plot file in the notebook

### Python

Can show a plot from a MIDI file on disk, or from any PrettyMIDI object, including coming from libraries such as Magenta (like [Magenta note-seq](https://github.com/magenta/note-seq)).

```python
from visual_midi import Plotter
from visual_midi import Preset
from pretty_midi import PrettyMIDI

plotter = Plotter()

# Loading a file on disk using PrettyMidi
# Loading a file on disk using PrettyMidi, and show
pm = PrettyMIDI("docs/example-01.mid")
plotter = Plotter()
plotter.show(pm, "/tmp/example-01.html")

# Converting to PrettyMidi from another library, like Magenta note-seq
import magenta.music as mm
pm = mm.midi_io.note_sequence_to_pretty_midi(sequence)
plotter = Plotter()
plotter.show(pm, "/tmp/example-02.html")
```

![Example 01](docs/example-01.png)


```python
from visual_midi import Plotter
from visual_midi import Preset
from pretty_midi import PrettyMIDI

# Using the `Preset` and `Plotter` to customize appearance (smaller plot)
pm = PrettyMIDI("docs/example-01.mid")
preset = Preset(plot_width=850)
plotter = Plotter(preset, plot_max_length_bar=4)
plotter.show(pm, "/tmp/example-01.html")
```

### Notebooks

See [example Jupyter notebook](./docs/example-01.ipynb):

```python
from visual_midi import Plotter
from visual_midi import Preset
from pretty_midi import PrettyMIDI

preset = Preset(plot_width=850)
plotter = Plotter(preset, plot_max_length_bar=4)
pm = PrettyMIDI("docs/example-01.mid")
plotter.show_notebook(pm)
```

![Example 01 - Notebook](docs/example-01-notebook.png)

### Command line

```bash
Expand Down
82 changes: 1 addition & 81 deletions README_short.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,84 +10,4 @@ pip install visual_midi

## Usage

### Python

```python
from visual_midi import Plotter
from pretty_midi import PrettyMIDI

pm = PrettyMIDI("docs/example-01.mid")
plotter = Plotter()
plotter.show(pm, "docs/example-01.html")
```

### Command line

```bash
visual_midi "midi_file_01.mid" "midi_file_02.mid"
```

### Flags

The same flags can be used both in Python and on the command line.

```bash
visual_midi -h
usage: visual_midi [-h] [--qpm QPM]
[--plot_pitch_range_start PLOT_PITCH_RANGE_START]
[--plot_pitch_range_stop PLOT_PITCH_RANGE_STOP]
[--plot_bar_range_start PLOT_BAR_RANGE_START]
[--plot_bar_range_stop PLOT_BAR_RANGE_STOP]
[--plot_max_length_bar PLOT_MAX_LENGTH_BAR]
[--bar_fill_alphas BAR_FILL_ALPHAS] [--coloring COLORING]
[--show_velocity SHOW_VELOCITY]
[--midi_time_signature MIDI_TIME_SIGNATURE]
[--live_reload LIVE_RELOAD] [--plot_width PLOT_WIDTH]
[--plot_height PLOT_HEIGHT] [--row_height ROW_HEIGHT]
[--show_bar SHOW_BAR] [--show_beat SHOW_BEAT]
[--title_text_font_size TITLE_TEXT_FONT_SIZE]
[--axis_label_text_font_size AXIS_LABEL_TEXT_FONT_SIZE]
[--axis_x_major_tick_out AXIS_X_MAJOR_TICK_OUT]
[--axis_y_major_tick_out AXIS_Y_MAJOR_TICK_OUT]
[--label_y_axis_offset_x LABEL_Y_AXIS_OFFSET_X]
[--label_y_axis_offset_y LABEL_Y_AXIS_OFFSET_Y]
[--axis_y_label_standoff AXIS_Y_LABEL_STANDOFF]
[--label_text_font_size LABEL_TEXT_FONT_SIZE]
[--label_text_font_style LABEL_TEXT_FONT_STYLE]
[--toolbar_location TOOLBAR_LOCATION]
[--stop_live_reload_button STOP_LIVE_RELOAD_BUTTON]
files [files ...]

positional arguments:
files

optional arguments:
-h, --help show this help message and exit
--qpm QPM
--plot_pitch_range_start PLOT_PITCH_RANGE_START
--plot_pitch_range_stop PLOT_PITCH_RANGE_STOP
--plot_bar_range_start PLOT_BAR_RANGE_START
--plot_bar_range_stop PLOT_BAR_RANGE_STOP
--plot_max_length_bar PLOT_MAX_LENGTH_BAR
--bar_fill_alphas BAR_FILL_ALPHAS
--coloring COLORING
--show_velocity SHOW_VELOCITY
--midi_time_signature MIDI_TIME_SIGNATURE
--live_reload LIVE_RELOAD
--plot_width PLOT_WIDTH
--plot_height PLOT_HEIGHT
--row_height ROW_HEIGHT
--show_bar SHOW_BAR
--show_beat SHOW_BEAT
--title_text_font_size TITLE_TEXT_FONT_SIZE
--axis_label_text_font_size AXIS_LABEL_TEXT_FONT_SIZE
--axis_x_major_tick_out AXIS_X_MAJOR_TICK_OUT
--axis_y_major_tick_out AXIS_Y_MAJOR_TICK_OUT
--label_y_axis_offset_x LABEL_Y_AXIS_OFFSET_X
--label_y_axis_offset_y LABEL_Y_AXIS_OFFSET_Y
--axis_y_label_standoff AXIS_Y_LABEL_STANDOFF
--label_text_font_size LABEL_TEXT_FONT_SIZE
--label_text_font_style LABEL_TEXT_FONT_STYLE
--toolbar_location TOOLBAR_LOCATION
--stop_live_reload_button STOP_LIVE_RELOAD_BUTTON
```
See full documentation at [Visual MIDI - GitHub](https://github.com/dubreuia/visual_midi).
12 changes: 6 additions & 6 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# TODO

- document with https://docs.python-guide.org/writing/documentation/#sphinx
- add bokeh server
- add docs and images
- release script
- add command line example `visual_midi --toolbar_location=None --plot_width=3840 --row_height=100 --title_text_font_size=65px --axis_label_text_font_size=55px --axis_x_major_tick_out=25 --axis_y_major_tick_out=100 --label_y_axis_offset_x=-85 --label_y_axis_offset_y=0.1 --axis_y_label_standoff=20 --label_text_font_size=60px --plot_pitch_range_start=68 --plot_pitch_range_stop=84 /home/alex/Project/hosting/magenta-resources/Chapter03/mono_beth_output/04/good/melody_rnn_attention_rnn_2019-08-15_164530.mid`

- [ ] Document with https://docs.python-guide.org/writing/documentation/#sphinx
- [ ] Add bokeh server
- [ ] Add docs and images
- [ ] Release script
- [ ] Add command line example `visual_midi --toolbar_location=None --plot_width=3840 --row_height=100 --title_text_font_size=65px --axis_label_text_font_size=55px --axis_x_major_tick_out=25 --axis_y_major_tick_out=100 --label_y_axis_offset_x=-85 --label_y_axis_offset_y=0.1 --axis_y_label_standoff=20 --label_text_font_size=60px --plot_pitch_range_start=68 --plot_pitch_range_stop=84 /home/alex/Project/hosting/magenta-resources/Chapter03/mono_beth_output/04/good/melody_rnn_attention_rnn_2019-08-15_164530.mid`
- [x] Make it work on Jupyer
Binary file added docs/example-01-notebook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions docs/example-01.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from visual_midi import Plotter\n",
"from visual_midi import Preset\n",
"from pretty_midi import PrettyMIDI"
]
},
{
"cell_type": "markdown",
"source": [
"Use the `Preset` object to customize the appearance (height, width, colors, etc.) of the plot, and the `Plotter` object to change the render view (number of bars to show, pitch range, etc.). The resulting plot still has all its bars (in this example, 16 bars), but the plot is \"zoomed in\" to the desired number of bars (int this example, 8 bas). You can still drag and zoom the plot."
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": null,
"outputs": [],
"source": [
"preset = Preset(plot_width=850)\n",
"plotter = Plotter(preset, plot_max_length_bar=4)\n",
"pm = PrettyMIDI(\"example-01.mid\")\n",
"plotter.show_notebook(pm)"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
20 changes: 15 additions & 5 deletions visual_midi/visual_midi.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import bokeh.plotting
from bokeh.colors.groups import purple as colors
from bokeh.embed import file_html
from bokeh.io import output_file
from bokeh.io import output_file, output_notebook
from bokeh.io import save
from bokeh.io import show
from bokeh.layouts import column
Expand Down Expand Up @@ -81,8 +81,7 @@ def _get_qpm(self, pm: PrettyMIDI):
return self._qpm
qpm = None
for tempo_change in pm.get_tempo_changes():
if (tempo_change.min() and tempo_change.max()
and tempo_change.min() == tempo_change.max()):
if tempo_change.min() and tempo_change.max() and tempo_change.min() == tempo_change.max():
if qpm:
raise Exception("Multiple tempo changes are not supported "
+ str(pm.get_tempo_changes()))
Expand Down Expand Up @@ -173,8 +172,7 @@ def plot(self, pm: PrettyMIDI):
index_instrument = index_instrument + 1

# Shows an empty plot even if there are no notes
if (first_note_start is None or last_note_end is None
or pitch_min is None or pitch_max is None):
if first_note_start is None or last_note_end is None or pitch_min is None or pitch_max is None:
pitch_min = self._MIN_PITCH
pitch_max = pitch_min + 5
first_note_start = 0
Expand Down Expand Up @@ -422,6 +420,18 @@ def show(self, pm: PrettyMIDI, filepath: str):
self._show_counter += 1
return plot

def show_notebook(self, pm: PrettyMIDI):
"""
Shows the pretty midi object as a plot file in the notebook.
:param pm: the PrettyMIDI instance to plot
:return: the bokeh plot layout
"""
plot = self.plot(pm)
output_notebook()
show(plot)
return plot


def console_entry_point():
flags_plot = [
Expand Down

0 comments on commit d49c5bb

Please sign in to comment.