Technical Documentation

A Python library for handling multitrack pianorolls.

Pypianoroll is an open source Python library for working with piano rolls. It provides essential tools for handling multitrack piano rolls, including efficient I/O as well as manipulation, visualization and evaluation tools.

Features

  • Manipulate multitrack piano rolls intuitively

  • Visualize multitrack piano rolls beautifully

  • Save and load multitrack piano rolls in a space-efficient format

  • Parse MIDI files into multitrack piano rolls

  • Write multitrack piano rolls into MIDI files

class pypianoroll.BinaryTrack(name: Optional[str] = None, program: Optional[int] = None, is_drum: Optional[bool] = None, pianoroll: Optional[numpy.ndarray] = None)[source]

A container for single-track, binary piano rolls.

name

Track name.

Type

str, optional

program

Program number according to General MIDI specification [1]. Defaults to 0 (Acoustic Grand Piano).

Type

int, 0-127, default: pypianoroll.DEFAULT_PROGRAM (0)

is_drum

Whether it is a percussion track.

Type

bool, default: pypianoroll.DEFAULT_IS_DRUM (False)

pianoroll

Piano-roll matrix. The first dimension represents time, and the second dimension represents pitch. Cast to bool if not of data type bool.

Type

ndarray, dtype=bool, shape=(?, 128), optional

References

  1. https://www.midi.org/specifications/item/gm-level-1-sound-set

copy() pypianoroll.track.BinaryTrack[source]

Return a copy of the track.

Returns

Return type

A copy of the object itself.

Notes

The piano-roll array is copied using numpy.copy().

set_nonzeros(value: int) pypianoroll.track.StandardTrack[source]

Assign a constant value to all nonzeros entries.

Parameters

value (int) – Value to assign.

Returns

Return type

Converted StandardTrack object.

class pypianoroll.Multitrack(name: Optional[str] = None, resolution: Optional[int] = None, tempo: Optional[numpy.ndarray] = None, beat: Optional[numpy.ndarray] = None, downbeat: Optional[numpy.ndarray] = None, tracks: Optional[Sequence[pypianoroll.track.Track]] = None)[source]

A container for multitrack piano rolls.

This is the core class of Pypianoroll. A Multitrack object can be constructed in the following ways.

name

Multitrack name.

Type

str, optional

resolution

Time steps per quarter note.

Type

int, default: pypianoroll.DEFAULT_RESOLUTION (24)

tempo

Tempo (in qpm) at each time step. Length is the total number of time steps. Cast to float if not of float type.

Type

ndarray, dtype=float, shape=(?, 1), optional

beat

A boolean array that indicates whether the time step contains a beat. Length is the total number of time steps. Cast to bool if not of bool type.

Type

ndarray, dtype=bool, shape=(?, 1), optional

downbeat

A boolean array that indicates whether the time step contains a downbeat, i.e., the first time step of a measure. Length is the total number of time steps. Cast to bool if not of bool type.

Type

ndarray, dtype=bool, shape=(?, 1), optional

tracks

Music tracks.

Type

sequence of pypianoroll.Track, default: []

append(track: pypianoroll.track.Track) pypianoroll.multitrack.MultitrackType[source]

Append a Track object to the track list.

Parameters

track (pypianoroll.Track) – Track to append.

Returns

Return type

Object itself.

binarize(threshold: float = 0) pypianoroll.multitrack.MultitrackType[source]

Binarize the piano rolls.

Parameters

threshold (int or float, default: 0) – Threshold to binarize the piano rolls.

Returns

Return type

Object itself.

blend(mode: Optional[str] = None) numpy.ndarray[source]

Return the blended pianoroll.

Parameters

mode ({'sum', 'max', 'any'}, default: 'sum') – Blending strategy to apply along the track axis. For ‘sum’ mode, integer summation is performed for binary piano rolls.

Returns

Blended piano roll.

Return type

ndarray, shape=(?, 128)

clip(lower: int = 0, upper: int = 127) pypianoroll.multitrack.MultitrackType[source]

Clip (limit) the the piano roll into [lower, upper].

Parameters
  • lower (int, default: 0) – Lower bound.

  • upper (int, default: 127) – Upper bound.

Returns

Return type

Object itself.

Note

Only affect StandardTrack instances.

copy()[source]

Return a copy of the multitrack.

Returns

Return type

A copy of the object itself.

Notes

Arrays are copied using numpy.copy().

count_beat() int[source]

Return the number of beats.

Returns

Number of beats.

Return type

int

Note

Return value is calculated based only on the attribute beat.

count_downbeat() int[source]

Return the number of downbeats.

Returns

Number of downbeats.

Return type

int

Note

Return value is calculated based only on the attribute downbeat.

get_beat_steps() numpy.ndarray[source]

Return the indices of time steps that contain beats.

Returns

Indices of time steps that contain beats.

Return type

ndarray, dtype=int

get_downbeat_steps() numpy.ndarray[source]

Return the indices of time steps that contain downbeats.

Returns

Indices of time steps that contain downbeats.

Return type

ndarray, dtype=int

get_length() int[source]

Return the maximum active length of the piano rolls.

Returns

Maximum active length (in time steps) of the piano rolls, where active length is the length of the piano roll without trailing silence.

Return type

int

get_max_length() int[source]

Return the maximum length of the piano rolls.

Returns

Maximum length (in time steps) of the piano rolls.

Return type

int

is_valid(attr: Optional[str] = None) bool[source]

Return True if an attribute is valid.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Whether the attribute has a valid type and value.

Return type

bool

is_valid_type(attr: Optional[str] = None) bool[source]

Return True if an attribute is of a valid type.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Whether the attribute is of a valid type.

Return type

bool

pad(pad_length) pypianoroll.multitrack.MultitrackType[source]

Pad the piano rolls.

Notes

The lengths of the resulting piano rolls are not guaranteed to be the same.

Parameters

pad_length (int) – Length to pad along the time axis.

Returns

Return type

Object itself.

See also

pypianoroll.Multitrack.pad_to_multiple()

Pad the piano rolls so that their lengths are some multiples.

pypianoroll.Multitrack.pad_to_same()

Pad the piano rolls so that they have the same length.

pad_to_multiple(factor: int) pypianoroll.multitrack.MultitrackType[source]

Pad the piano rolls so that their lengths are some multiples.

Pad the piano rolls at the end along the time axis of the minimum length that makes the lengths of the resulting piano rolls multiples of factor.

Parameters

factor (int) – The value which the length of the resulting piano rolls will be a multiple of.

Returns

Return type

Object itself.

Notes

Lengths of the resulting piano rolls are necessarily the same.

See also

pypianoroll.Multitrack.pad()

Pad the piano rolls.

pypianoroll.Multitrack.pad_to_same()

Pad the piano rolls so that they have the same length.

pad_to_same() pypianoroll.multitrack.MultitrackType[source]

Pad the piano rolls so that they have the same length.

Pad shorter piano rolls at the end along the time axis so that the resulting piano rolls have the same length.

Returns

Return type

Object itself.

See also

pypianoroll.Multitrack.pad()

Pad the piano rolls.

pypianoroll.Multitrack.pad_to_multiple()

Pad the piano rolls so that their lengths are some multiples.

plot(axs: Optional[Sequence[matplotlib.axes._axes.Axes]] = None, **kwargs) List[matplotlib.axes._axes.Axes][source]

Plot the multitrack piano roll.

Refer to pypianoroll.plot_multitrack() for full documentation.

remove_empty() pypianoroll.multitrack.MultitrackType[source]

Remove tracks with empty pianorolls.

save(path: str, compressed: bool = True)[source]

Save to a NPZ file.

Refer to pypianoroll.save() for full documentation.

set_nonzeros(value: int) pypianoroll.multitrack.MultitrackType[source]

Assign a constant value to all nonzero entries.

Parameters

value (int) – Value to assign.

Returns

Return type

Object itself.

set_resolution(resolution: int, rounding: str = 'round') pypianoroll.multitrack.MultitrackType[source]

Set the resolution.

Parameters
  • resolution (int) – Target resolution.

  • rounding ({'round', 'ceil', 'floor'}, default: 'round') – Rounding mode.

Returns

Return type

Object itself.

stack() numpy.ndarray[source]

Return the piano rolls stacked as a 3D tensor.

Returns

Stacked piano roll, provided as (track, time, pitch).

Return type

ndarray, shape=(?, ?, 128)

to_pretty_midi(**kwargs)[source]

Return as a PrettyMIDI object.

Refer to pypianoroll.to_pretty_midi() for full documentation.

transpose(semitone: int) pypianoroll.multitrack.MultitrackType[source]

Transpose the piano rolls by a number of semitones.

Parameters

semitone (int) – Number of semitones to transpose. A positive value raises the pitches, while a negative value lowers the pitches.

Returns

Return type

Object itself.

Notes

Drum tracks are skipped.

trim(start: Optional[int] = None, end: Optional[int] = None) pypianoroll.multitrack.MultitrackType[source]

Trim the trailing silences of the piano rolls.

Parameters
  • start (int, default: 0) – Start time.

  • end (int, optional) – End time. Defaults to active length.

Returns

Return type

Object itself.

validate(attr=None) pypianoroll.multitrack.MultitrackType[source]

Raise an error if an attribute has an invalid type or value.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Return type

Object itself.

validate_type(attr=None)[source]

Raise an error if an attribute has an invalid type.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Return type

Object itself.

write(path: str)[source]

Write to a MIDI file.

Refer to pypianoroll.write() for full documentation.

class pypianoroll.StandardTrack(name: Optional[str] = None, program: Optional[int] = None, is_drum: Optional[bool] = None, pianoroll: Optional[numpy.ndarray] = None)[source]

A container for single-track piano rolls with velocities.

name

Track name.

Type

str, optional

program

Program number according to General MIDI specification [1]. Defaults to 0 (Acoustic Grand Piano).

Type

int, 0-127, default: pypianoroll.DEFAULT_PROGRAM (0)

is_drum

Whether it is a percussion track.

Type

bool, default: pypianoroll.DEFAULT_IS_DRUM (False)

pianoroll

Piano-roll matrix. The first dimension represents time, and the second dimension represents pitch. Cast to uint8 if not of data type uint8.

Type

ndarray, dtype=uint8, shape=(?, 128), optional

References

  1. https://www.midi.org/specifications/item/gm-level-1-sound-set

clip(lower: int = 0, upper: int = 127) pypianoroll.track.StandardTrackType[source]

Clip (limit) the the piano roll into [lower, upper].

Parameters
  • lower (int, default: 0) – Lower bound.

  • upper (int, default: 127) – Upper bound.

Returns

Return type

Object itself.

copy() pypianoroll.track.StandardTrack[source]

Return a copy of the track.

Returns

Return type

A copy of the object itself.

Notes

The piano-roll array is copied using numpy.copy().

set_nonzeros(value: int) pypianoroll.track.StandardTrackType[source]

Assign a constant value to all nonzeros entries.

Parameters

value (int) – Value to assign.

Returns

Return type

Object itself.

class pypianoroll.Track(name: Optional[str] = None, program: Optional[int] = None, is_drum: Optional[bool] = None, pianoroll: Optional[numpy.ndarray] = None)[source]

A generic container for single-track piano rolls.

name

Track name.

Type

str, optional

program

Program number according to General MIDI specification [1]. Defaults to 0 (Acoustic Grand Piano).

Type

int, 0-127, default: pypianoroll.DEFAULT_PROGRAM (0)

is_drum

Whether it is a percussion track.

Type

bool, pypianoroll.DEFAULT_IS_DRUM (False)

pianoroll

Piano-roll matrix. The first dimension represents time, and the second dimension represents pitch.

Type

ndarray, shape=(?, 128), optional

References

  1. https://www.midi.org/specifications/item/gm-level-1-sound-set

binarize(threshold: float = 0) pypianoroll.track.BinaryTrack[source]

Binarize the track.

This will binarize the piano roll by the given threshold.

Parameters

threshold (int or float, default: 0) – Threshold.

Returns

Return type

Converted BinaryTrack object.

copy() pypianoroll.track.Track[source]

Return a copy of the track.

Returns

Return type

A copy of the object itself.

Notes

The piano-roll array is copied using numpy.copy().

get_length() int[source]

Return the active length of the piano roll.

Returns

Length (in time steps) of the piano roll without trailing silence.

Return type

int

is_valid(attr: Optional[str] = None) bool[source]

Return True if an attribute is valid.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Whether the attribute has a valid type and value.

Return type

bool

is_valid_type(attr: Optional[str] = None) bool[source]

Return True if an attribute is of a valid type.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Whether the attribute is of a valid type.

Return type

bool

pad(pad_length: int) pypianoroll.track.TrackType[source]

Pad the piano roll.

Parameters

pad_length (int) – Length to pad along the time axis.

Returns

Return type

Object itself.

See also

pypianoroll.Track.pad_to_multiple()

Pad the piano roll so that its length is some multiple.

pad_to_multiple(factor: int) pypianoroll.track.TrackType[source]

Pad the piano roll so that its length is some multiple.

Pad the piano roll at the end along the time axis of the minimum length that makes the length of the resulting piano roll a multiple of factor.

Parameters

factor (int) – The value which the length of the resulting piano roll will be a multiple of.

Returns

Return type

Object itself.

See also

pypianoroll.Track.pad()

Pad the piano roll.

plot(ax: Optional[matplotlib.axes._axes.Axes] = None, **kwargs) matplotlib.axes._axes.Axes[source]

Plot the piano roll.

Refer to pypianoroll.plot_track() for full documentation.

standardize() pypianoroll.track.StandardTrack[source]

Standardize the track.

This will clip the piano roll to [0, 127] and cast to np.uint8.

Returns

Return type

Converted StandardTrack object.

transpose(semitone: int) pypianoroll.track.TrackType[source]

Transpose the piano roll by a number of semitones.

Parameters

semitone (int) – Number of semitones to transpose. A positive value raises the pitches, while a negative value lowers the pitches.

Returns

Return type

Object itself.

trim(start: Optional[int] = None, end: Optional[int] = None) pypianoroll.track.TrackType[source]

Trim the piano roll.

Parameters
  • start (int, default: 0) – Start time.

  • end (int, optional) – End time. Defaults to active length.

Returns

Return type

Object itself.

validate(attr=None)[source]

Raise an error if an attribute has an invalid type or value.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Return type

Object itself.

validate_type(attr=None)[source]

Raise an error if an attribute has an invalid type.

Parameters

attr (str) – Attribute to validate. Defaults to validate all attributes.

Returns

Return type

Object itself.

pypianoroll.binarize(obj: Union[pypianoroll.multitrack.Multitrack, pypianoroll.track.StandardTrack], threshold: int = 0)[source]

Binarize the piano roll(s).

Parameters
pypianoroll.clip(obj: pypianoroll.core.MultitrackType, lower: int = 0, upper: int = 127) pypianoroll.core.MultitrackType[source]

Clip (limit) the the piano roll(s) into [lower, upper].

Parameters
Returns

Return type

Object itself.

pypianoroll.drum_in_pattern_rate(pianoroll: numpy.ndarray, resolution: int, tolerance: float = 0.1) float[source]

Return the ratio of drum notes in a certain drum pattern.

The drum-in-pattern rate is defined as the ratio of the number of notes in a certain scale to the total number of notes. Only drum tracks are considered. Return NaN if no drum note is found. This metric is used in [1].

\[drum\_in\_pattern\_rate = \frac{ \#(drum\_notes\_in\_pattern)}{\#(drum\_notes)}\]
Parameters
  • pianoroll (ndarray) – Piano roll to evaluate.

  • resolution (int) – Time steps per beat.

  • tolerance (float, default: 0.1) – Tolerance.

Returns

Drum-in-pattern rate.

Return type

float

References

  1. Hao-Wen Dong, Wen-Yi Hsiao, Li-Chia Yang, and Yi-Hsuan Yang, “MuseGAN: Multi-track sequential generative adversarial networks for symbolic music generation and accompaniment,” in Proceedings of the 32nd AAAI Conference on Artificial Intelligence (AAAI), 2018.

pypianoroll.empty_beat_rate(pianoroll: numpy.ndarray, resolution: int) float[source]

Return the ratio of empty beats.

The empty-beat rate is defined as the ratio of the number of empty beats (where no note is played) to the total number of beats. Return NaN if song length is zero.

\[empty\_beat\_rate = \frac{\#(empty\_beats)}{\#(beats)}\]
Parameters

pianoroll (ndarray) – Piano roll to evaluate.

Returns

Empty-beat rate.

Return type

float

pypianoroll.from_pretty_midi(midi: pretty_midi.pretty_midi.PrettyMIDI, resolution: int = 24, mode: str = 'max', algorithm: str = 'normal', collect_onsets_only: bool = False, first_beat_time: Optional[float] = None) pypianoroll.multitrack.Multitrack[source]

Return a Multitrack object converted from a PrettyMIDI object.

Parse a pretty_midi.PrettyMIDI object. The data type of the resulting piano rolls is automatically determined (int if ‘mode’ is ‘sum’ and np.uint8 if mode is ‘max’).

Parameters
  • midi (pretty_midi.PrettyMIDI) – PrettyMIDI object to parse.

  • mode ({'max', 'sum'}, default: 'max') – Merging strategy for duplicate notes.

  • algorithm ({'normal', 'strict', 'custom'}, default: 'normal') – Algorithm for finding the location of the first beat (see Notes).

  • collect_onsets_only (bool, default: False) – True to collect only the onset of the notes (i.e. note on events) in all tracks, where the note off and duration information are discarded. False to parse regular piano rolls.

  • first_beat_time (float, optional) – Location of the first beat, in sec. Required and only effective when using ‘custom’ algorithm.

Returns

Converted Multitrack object.

Return type

pypianoroll.Multitrack

Notes

There are three algorithms for finding the location of the first beat:

  • ‘normal’ : Estimate the location of the first beat using pretty_midi.PrettyMIDI.estimate_beat_start().

  • ‘strict’ : Set the location of the first beat to the time of the first time signature change. Raise a RuntimeError if no time signature change is found.

  • ‘custom’ : Set the location of the first beat to the value of argument first_beat_time. Raise a ValueError if first_beat_time is not given.

If an incomplete beat before the first beat is found, an additional beat will be added before the (estimated) beat starting time. However, notes before the (estimated) beat starting time for more than one beat are dropped.

pypianoroll.in_scale_rate(pianoroll: numpy.ndarray, root: int = 3, mode: str = 'major') float[source]

Return the ratio of pitches in a certain musical scale.

The pitch-in-scale rate is defined as the ratio of the number of notes in a certain scale to the total number of notes. Drum tracks are ignored. Return NaN if no note is found. This metric is used in [1].

\[pitch\_in\_scale\_rate = \frac{\#(notes\_in\_scale)}{\#(notes)}\]
Parameters
  • pianoroll (ndarray) – Piano roll to evaluate.

  • root (int) – Root of the scale.

  • mode (str, {'major', 'minor'}) – Mode of the scale.

Returns

Pitch-in-scale rate.

Return type

float

See also

muspy.scale_consistency()

Compute the largest pitch-in-class rate.

References

  1. Hao-Wen Dong, Wen-Yi Hsiao, Li-Chia Yang, and Yi-Hsuan Yang, “MuseGAN: Multi-track sequential generative adversarial networks for symbolic music generation and accompaniment,” in Proceedings of the 32nd AAAI Conference on Artificial Intelligence (AAAI), 2018.

pypianoroll.load(path: Union[str, pathlib.Path]) pypianoroll.multitrack.Multitrack[source]

Load a NPZ file into a Multitrack object.

Supports only files previously saved by pypianoroll.save().

Parameters

path (str or Path) – Path to the file to load.

See also

pypianoroll.save()

Save a Multitrack object to a NPZ file.

pypianoroll.read()

Read a MIDI file into a Multitrack object.

pypianoroll.n_pitch_classes_used(pianoroll: numpy.ndarray) int[source]

Return the number of unique pitch classes used.

Parameters

pianoroll (ndarray) – Piano roll to evaluate.

Returns

Number of unique pitch classes used.

Return type

int

See also

pypianoroll.n_pitches_used()

Compute the number of unique pitches used.

pypianoroll.n_pitches_used(pianoroll: numpy.ndarray) int[source]

Return the number of unique pitches used.

Parameters

pianoroll (ndarray) – Piano roll to evaluate.

Returns

Number of unique pitch classes used.

Return type

int

See also

pypianoroll.n_pitch_class_used()

Compute the number of unique pitch classes used.

pypianoroll.pad(obj: pypianoroll.core.MultitrackOrTrackType, pad_length: int) pypianoroll.core.MultitrackOrTrackType[source]

Pad the piano roll(s).

Notes

The lengths of the resulting piano rolls are not guaranteed to be the same. See pypianoroll.Multitrack.pad_to_same().

Parameters
Returns

Return type

Object itself.

See also

pypianoroll.pad_to_same()

Pad the piano rolls so that they have the same length.

pypianoroll.pad_to_multiple()

Pad the piano rolls so that their lengths are some multiples.

pypianoroll.pad_to_multiple(obj: pypianoroll.core.MultitrackOrTrackType, factor: int) pypianoroll.core.MultitrackOrTrackType[source]

Pad the piano roll(s) so that their lengths are some multiples.

Pad the piano rolls at the end along the time axis of the minimum length that makes the lengths of the resulting piano rolls multiples of factor.

Parameters
Returns

Return type

Object itself.

Notes

Lengths of the resulting piano rolls are necessarily the same.

See also

pypianoroll.pad()

Pad the piano rolls.

pypianoroll.pad_to_same()

Pad the piano rolls so that they have the same length.

pypianoroll.pad_to_same(obj: pypianoroll.core.MultitrackType) pypianoroll.core.MultitrackType[source]

Pad the piano rolls so that they have the same length.

Pad shorter piano rolls at the end along the time axis so that the resulting piano rolls have the same length.

Parameters

obj (pypianoroll.Multitrack) – Object to pad.

Returns

Return type

Object itself.

See also

pypianoroll.pad()

Pad the piano rolls.

pypianoroll.pad_to_multiple()

Pad the piano rolls so that their lengths are some multiples.

pypianoroll.pitch_range(pianoroll) float[source]

Return the pitch range.

Returns

Pitch range (in semitones), i.e., difference between the highest and the lowest active pitches.

Return type

int or nan

See also

pypianoroll.pitch_range_tuple()

Return the pitch range as a tuple.

pypianoroll.pitch_range_tuple(pianoroll) Tuple[float, float][source]

Return the pitch range as a tuple (lowest, highest).

Returns

  • int or nan – Highest active pitch.

  • int or nan – Lowest active pitch.

See also

pypianoroll.pitch_range()

Compute the pitch range.

pypianoroll.plot(obj: Union[pypianoroll.track.Track, pypianoroll.multitrack.Multitrack], **kwargs) Union[List[matplotlib.axes._axes.Axes], matplotlib.axes._axes.Axes][source]

Plot the object.

See pypianoroll.plot_multitrack() and pypianoroll.plot_track() for full documentation.

pypianoroll.plot_multitrack(multitrack: Multitrack, axs: Sequence[matplotlib.axes._axes.Axes] = None, mode: str = 'separate', track_label: str = 'name', preset: str = 'full', cmaps: Sequence[str] = None, xtick: str = 'auto', ytick: str = 'octave', xticklabel: bool = True, yticklabel: str = 'auto', tick_loc: Sequence[str] = ('bottom', 'left'), tick_direction: str = 'in', label: str = 'both', grid_axis: str = 'both', grid_linestyle: str = ':', grid_linewidth: float = 0.5, **kwargs) List[matplotlib.axes._axes.Axes][source]

Plot the multitrack.

Parameters
  • multitrack (pypianoroll.Multitrack) – Multitrack to plot.

  • axs (sequence of matplotlib.axes.Axes, optional) – Axes to plot the tracks on.

  • mode ({'separate', 'blended', 'hybrid'}, default: 'separate') – Plotting strategy for visualizing multiple tracks. For ‘separate’ mode, plot each track separately. For ‘blended’, blend and plot the pianoroll as a colored image. For ‘hybrid’ mode, drum tracks are blended into a ‘Drums’ track and all other tracks are blended into an ‘Others’ track.

  • track_label ({'name', 'program', 'family', 'off'}) – Track label format. When mode is ‘hybrid’, all options other than ‘off’ will label the two track with ‘Drums’ and ‘Others’.

  • preset ({'full', 'frame', 'plain'}, default: 'full') – Preset theme to use. For ‘full’ preset, ticks, grid and labels are on. For ‘frame’ preset, ticks and grid are both off. For ‘plain’ preset, the x- and y-axis are both off.

  • cmaps (tuple or list) – Colormaps. Will be passed to matplotlib.pyplot.imshow(). Only effective when pianoroll is 2D. Defaults to ‘Blues’. If mode is ‘separate’, defaults to (‘Blues’, ‘Oranges’, ‘Greens’, ‘Reds’, ‘Purples’, ‘Greys’). If mode is ‘blended’, defaults to (‘hsv’). If mode is ‘hybrid’, defaults to (‘Blues’, ‘Greens’).

  • **kwargs – Keyword arguments to pass to pypianoroll.plot_pianoroll().

Returns

(Created) list of Axes objects.

Return type

list of matplotlib.axes.Axes

pypianoroll.plot_pianoroll(ax: matplotlib.axes._axes.Axes, pianoroll: numpy.ndarray, is_drum: bool = False, resolution: Optional[int] = None, downbeats: Optional[numpy.ndarray] = None, preset: str = 'full', cmap: str = 'Blues', xtick: str = 'auto', ytick: str = 'octave', xticklabel: bool = True, yticklabel: str = 'auto', tick_loc: Sequence[str] = ('bottom', 'left'), tick_direction: str = 'in', label: str = 'both', grid_axis: str = 'both', grid_linestyle: str = ':', grid_linewidth: float = 0.5, **kwargs)[source]

Plot a piano roll.

Parameters
  • ax (matplotlib.axes.Axes) – Axes to plot the piano roll on.

  • pianoroll (ndarray, shape=(?, 128), (?, 128, 3) or (?, 128, 4)) – Piano roll to plot. For a 3D piano-roll array, the last axis can be either RGB or RGBA.

  • is_drum (bool, default: False) – Whether it is a percussion track.

  • resolution (int) – Time steps per quarter note. Required if xtick is ‘beat’.

  • downbeats (list) – Boolean array that indicates whether the time step contains a downbeat (i.e., the first time step of a bar).

  • preset ({'full', 'frame', 'plain'}, default: 'full') – Preset theme. For ‘full’ preset, ticks, grid and labels are on. For ‘frame’ preset, ticks and grid are both off. For ‘plain’ preset, the x- and y-axis are both off.

  • cmap (str or matplotlib.colors.Colormap, default: ‘Blues’) – Colormap. Will be passed to matplotlib.pyplot.imshow(). Only effective when pianoroll is 2D.

  • xtick ({'auto', 'beat', 'step', 'off'}) – Tick format for the x-axis. For ‘auto’ mode, set to ‘beat’ if resolution is given, otherwise set to ‘step’. Defaults to ‘auto’.

  • ytick ({'octave', 'pitch', 'off'}, default: 'octave') – Tick format for the y-axis.

  • xticklabel (bool) – Whether to add tick labels along the x-axis.

  • yticklabel ({'auto', 'name', 'number', 'off'}, default: 'auto') – Tick label format for the y-axis. For ‘name’ mode, use pitch name as tick labels. For ‘number’ mode, use pitch number. For ‘auto’ mode, set to ‘name’ if ytick is ‘octave’ and ‘number’ if ytick is ‘pitch’.

  • tick_loc (sequence of {'bottom', 'top', 'left', 'right'}) – Tick locations. Defaults to (‘bottom’, ‘left’).

  • tick_direction ({'in', 'out', 'inout'}, default: 'in') – Tick direction.

  • label ({'x', 'y', 'both', 'off'}, default: 'both') – Whether to add labels to x- and y-axes.

  • grid_axis ({'x', 'y', 'both', 'off'}, default: 'both') – Whether to add grids to the x- and y-axes.

  • grid_linestyle (str) – Grid line style. Will be passed to matplotlib.axes.Axes.grid().

  • grid_linewidth (float) – Grid line width. Will be passed to matplotlib.axes.Axes.grid().

  • **kwargs – Keyword arguments to be passed to matplotlib.axes.Axes.imshow().

pypianoroll.plot_track(track: Track, ax: matplotlib.axes._axes.Axes = None, **kwargs) matplotlib.axes._axes.Axes[source]

Plot a track.

Parameters
Returns

(Created) Axes object.

Return type

matplotlib.axes.Axes

pypianoroll.polyphonic_rate(pianoroll: numpy.ndarray, threshold: float = 2) float[source]

Return the ratio of time steps where multiple pitches are on.

The polyphony rate is defined as the ratio of the number of time steps where multiple pitches are on to the total number of time steps. Drum tracks are ignored. Return NaN if song length is zero. This metric is used in [1], where it is called polyphonicity.

\[polyphony\_rate = \frac{ \#(time\_steps\_where\_multiple\_pitches\_are\_on) }{ \#(time\_steps) }\]
Parameters
  • pianoroll (ndarray) – Piano roll to evaluate.

  • threshold (int) – Threshold of number of pitches to count into the numerator.

Returns

Polyphony rate.

Return type

float

References

  1. Hao-Wen Dong, Wen-Yi Hsiao, Li-Chia Yang, and Yi-Hsuan Yang, “MuseGAN: Multi-track sequential generative adversarial networks for symbolic music generation and accompaniment,” in Proceedings of the 32nd AAAI Conference on Artificial Intelligence (AAAI), 2018.

pypianoroll.qualified_note_rate(pianoroll: numpy.ndarray, threshold: float = 2) float[source]

Return the ratio of the number of the qualified notes.

The qualified note rate is defined as the ratio of the number of qualified notes (notes longer than threshold, in time steps) to the total number of notes. Return NaN if no note is found.

\[qualified\_note\_rate = \frac{ \#(notes\_longer\_than\_the\_threshold) }{ \#(notes) }\]
Parameters
  • pianoroll (ndarray) – Piano roll to evaluate.

  • threshold (int) – Threshold of note length to count into the numerator.

Returns

Qualified note rate.

Return type

float

References

  1. Hao-Wen Dong, Wen-Yi Hsiao, Li-Chia Yang, and Yi-Hsuan Yang, “MuseGAN: Multi-track sequential generative adversarial networks for symbolic music generation and accompaniment,” in Proceedings of the 32nd AAAI Conference on Artificial Intelligence (AAAI), 2018.

pypianoroll.read(path: Union[str, pathlib.Path], **kwargs) pypianoroll.multitrack.Multitrack[source]

Read a MIDI file into a Multitrack object.

Parameters

See also

pypianoroll.write()

Write a Multitrack object to a MIDI file.

pypianoroll.load()

Load a NPZ file into a Multitrack object.

pypianoroll.save(path: Union[str, pathlib.Path], multitrack: Multitrack, compressed: bool = True)[source]

Save a Multitrack object to a NPZ file.

Parameters
  • path (str or Path) – Path to the NPZ file to save.

  • multitrack (pypianoroll.Multitrack) – Multitrack to save.

  • compressed (bool, default: True) – Whether to save to a compressed NPZ file.

Notes

To reduce the file size, the piano rolls are first converted to instances of scipy.sparse.csc_matrix. The component arrays are then collected and saved to a npz file.

See also

pypianoroll.load()

Load a NPZ file into a Multitrack object.

pypianoroll.write()

Write a Multitrack object to a MIDI file.

pypianoroll.set_nonzeros(obj: Union[pypianoroll.multitrack.Multitrack, pypianoroll.track.StandardTrack, pypianoroll.track.BinaryTrack], value: int)[source]

Assign a constant value to all nonzeros entries.

Parameters
pypianoroll.set_resolution(obj: pypianoroll.core.MultitrackType, resolution: int, rounding: str = 'round') pypianoroll.core.MultitrackType[source]

Downsample the piano rolls by a factor.

Parameters
  • obj (pypianoroll.Multitrack) – Object to downsample.

  • resolution (int) – Target resolution.

  • rounding ({'round', 'ceil', 'floor'}, default: 'round') – Rounding mode.

Returns

Return type

Object itself.

pypianoroll.to_pretty_midi(multitrack: Multitrack, default_tempo: float = None, default_velocity: int = 64) pretty_midi.pretty_midi.PrettyMIDI[source]

Return a Multitrack object as a PrettyMIDI object.

Parameters
  • default_tempo (int, default: pypianoroll.DEFAULT_TEMPO (120)) – Default tempo to use. If attribute tempo is available, use its first element.

  • default_velocity (int, default: pypianoroll.DEFAULT_VELOCITY (64)) – Default velocity to assign to binarized tracks.

Returns

Converted PrettyMIDI object.

Return type

pretty_midi.PrettyMIDI

Notes

  • Tempo changes are not supported.

  • Time signature changes are not supported.

  • The velocities of the converted piano rolls will be clipped to [0, 127].

  • Adjacent nonzero values of the same pitch will be considered a single note with their mean as its velocity.

pypianoroll.tonal_distance(pianoroll_1: numpy.ndarray, pianoroll_2: numpy.ndarray, resolution: int, radii: Sequence[float] = (1.0, 1.0, 0.5)) float[source]

Return the tonal distance [1] between the two input piano rolls.

Parameters
  • pianoroll_1 (ndarray) – First piano roll to evaluate.

  • pianoroll_2 (ndarray) – Second piano roll to evaluate.

  • resolution (int) – Time steps per beat.

  • radii (tuple of float) – Radii of the three tonal circles (see Equation 3 in [1]).

References

  1. Christopher Harte, Mark Sandler, and Martin Gasser, “Detecting harmonic change in musical audio,” in Proceedings of the 1st ACM workshop on Audio and music computing multimedia, 2006.

pypianoroll.transpose(obj: pypianoroll.core.MultitrackOrTrackType, semitone: int) pypianoroll.core.MultitrackOrTrackType[source]

Transpose the piano roll(s) by a number of semitones.

Positive values are for a higher key, while negative values are for a lower key. Drum tracks are ignored.

Parameters
  • obj (pypianoroll.Multitrack or pypianoroll.Track) – Object to transpose.

  • semitone (int) – Number of semitones to transpose. A positive value raises the pitches, while a negative value lowers the pitches.

Returns

Return type

Object itself.

pypianoroll.trim(obj: pypianoroll.core.MultitrackOrTrackType, start: Optional[int] = None, end: Optional[int] = None) pypianoroll.core.MultitrackOrTrackType[source]

Trim the trailing silences of the piano roll(s).

Parameters
Returns

Return type

Object itself.

pypianoroll.write(path: str, multitrack: Multitrack)[source]

Write a Multitrack object to a MIDI file.

Parameters

See also

pypianoroll.read()

Read a MIDI file into a Multitrack object.

pypianoroll.save()

Save a Multitrack object to a NPZ file.