Rhythm class#

This class is used for making/working with rhythms in the musical sense.

class thebeat.music.Rhythm(iois, time_signature=(4, 4), beat_ms=500, is_played=None, name=None)[source]#

The Rhythm class can be used for working sequences that are rhythmical in the musical sense. This means that in addition to having inter-onset intervals (IOIs) that represent the timing of the events in the sequence, Rhythm objects have musical properties such as a time signature, a beat duration, and they may contain rests.

The Rhythm class is also used as the basis for a Melody.

For more info on these properties, please refer to the class’s __init__().

__init__(iois, time_signature=(4, 4), beat_ms=500, is_played=None, name=None)[source]#

Constructs a Rhythm object.

Parameters:
  • iois – An iterable of inter-onset intervals (IOIs). For instance: [500, 500, 400, 200].

  • time_signature (default: (4, 4)) – A musical time signature, for instance: (4, 4). As a reminder: the upper number indicates how many beats there are in a bar. The lower number indicates the denominator of the value that indicates one beat. So, in (4, 8) time, a bar would be filled if we have four \(\frac{1}{8}\) th notes. Note: This parameter is a tuple and not a Fraction, since time signatures should not be simplified (e.g., a 6/8 signature will not be simplified to 3/4).

  • beat_ms (default: 500) – The value (in milliseconds) for the beat, i.e. the duration of a \(\frac{1}{4}\) th note if the lower number in the time signature is 4.

  • is_played (default: None) – A list or array containing booleans indicating whether a note should be played or not. Defaults to [True, True, True, ...].

  • name (default: None) – Optionally, you can give the Sequence object a name. This is used when printing, plotting, or writing the Sequence object. It can always be retrieved and changed via Rhythm.name.

Examples

>>> iois = [500, 250, 250, 500, 500]
>>> r = Rhythm(iois)
>>> print(r.onsets)
[   0.  500.  750. 1000. 1500.]
>>> iois = [500, 250, 250, 500]
>>> r = Rhythm(iois=iois, time_signature=(3, 4), beat_ms=250)
>>> print(r.note_values)
[Fraction(1, 2), Fraction(1, 4), Fraction(1, 4), Fraction(1, 2)]
copy(deep=True)[source]#

Returns a copy of itself. See copy.copy() for more information.

Parameters:

deep (bool, default: True) – If True, a deep copy is returned. If False, a shallow copy is returned.

property duration: float64#

Property that returns the summed total of the inter-onset intervals.

classmethod from_integer_ratios(numerators, time_signature=(4, 4), beat_ms=500, is_played=None, name=None)[source]#

Very simple conveniance class method that constructs a Rhythm object by calculating the inter-onset intervals (IOIs) as numerators * beat_ms.

Parameters:
  • numerators – Contains the numerators of the integer ratios. For instance: [1, 2, 4].

  • time_signature (default: (4, 4)) – A musical time signature, for instance: (4, 4). As a reminder: the upper number indicates how many beats there are in a bar. The lower number indicates the denominator of the value that indicates one beat. So, in (4, 8) time, a bar would be filled if we have four \(\frac{1}{8}\) th notes.

  • beat_ms (default: 500) – The value (in milliseconds) for the beat, i.e. the duration of a \(\frac{1}{4}\) th note if the lower number in the time signature is 4.

  • is_played (default: None) – A list or array containing booleans indicating whether a note should be played or not. Defaults to [True, True, True, ...].

  • name (default: None) – Optionally, you can give the Sequence object a name. This is used when printing, plotting, or writing the Sequence object. It can always be retrieved and changed via Rhythm.name.

classmethod from_note_values(fractions, time_signature=(4, 4), beat_ms=500, is_played=None, name=None)[source]#

This class method can be used for creating a Rhythm on the basis of fractions (i.e., note values). The fractions can be input either as floats (e.g. 0.25) or as fractions.Fraction objects.

Parameters:
  • fractions – The fractions of the rhythm. For instance: [1/4, 1/2, 1/4].

  • time_signature (default: (4, 4)) – The time signature of the rhythm. For instance: (4, 4).

  • beat_ms (default: 500) – The duration of a beat in milliseconds. This refers to the duration of the denominator of the time signature.

  • is_played (default: None) – A list of booleans indicating which notes are played. If None, all notes are played.

  • name (default: None) – A name for the rhythm.

Example

A sequence of IOIs [250, 500, 1000, 250] has a total duration of 2000 ms. If the time signature is 4/4 (time_signature=(4, 4)), and each quarter-note beat corresponds to 250 ms (beat_ms=250), then the note values correspond to a quarter note, a half note, a full note, and another quarter note. Consequently, this method will return [Fraction(1, 4), Fraction(1, 2), Fraction(1, 1), Fraction(1, 4)].

Examples

>>> r = Rhythm.from_note_values([1/4, 1/4, 1/4, 1/4], time_signature=(4, 4), beat_ms=500)
>>> import fractions
>>> dotted_halfnote = fractions.Fraction(3, 4)
>>> halfnote = fractions.Fraction(1, 2)
>>> r = Rhythm.from_note_values([dotted_halfnote, halfnote], time_signature=(5, 4), beat_ms=500)
>>> r = Rhythm.from_note_values([1/8, 1/8, 1/8, 1/8], time_signature=(4, 8), beat_ms=500)
classmethod generate_isochronous(n_bars=1, time_signature=(4, 4), beat_ms=500, is_played=None, name=None)[source]#

Simply generates an isochronous (i.e. with equidistant inter-onset intervals) rhythm. Will have the bars filled with intervals of beat_ms.

Parameters:
  • n_bars (default: 1) – The desired number of musical bars.

  • time_signature (default: (4, 4)) – A musical time signature, for instance: (4, 4). As a reminder: the upper number indicates how many beats there are in a bar. The lower number indicates the denominator of the value that indicates one beat. So, in (4, 8) time, a bar would be filled if we have four \(\frac{1}{8}\) th notes.

  • beat_ms (default: 500) – The value (in milliseconds) for the beat, i.e. the duration of a \(\frac{1}{4}\) th note if the lower number in the time signature is 4.

  • is_played (default: None) – A list or array containing booleans indicating whether a note should be played or not. Defaults to [True, True, True, ...].

  • name (default: None) – If desired, one can give a rhythm a name. This is for instance used when printing the rhythm, or when plotting the rhythm. It can always be retrieved and changed via Rhythm.name.

classmethod generate_random_rhythm(n_bars=1, beat_ms=500, time_signature=(4, 4), allowed_note_values=None, n_rests=0, rng=None, name=None)[source]#

This function generates a random rhythmic sequence on the basis of the provided parameters.

It does so by first generating all possible combinations of note values that amount to one bar based on the allowed_note_values parameter, and then selecting (with replacement) n_bars combinations out of the possibilities.

Parameters:
  • n_bars (default: 1) – The desired number of musical bars.

  • beat_ms (default: 500) – The value (in milliseconds) for the beat, i.e. the duration of a \(\frac{1}{4}\) th note if the lower number in the time signature is 4.

  • time_signature (default: (4, 4)) – A musical time signature, for instance: (4, 4). As a reminder: the upper number indicates how many beats there are in a bar. The lower number indicates the denominator of the value that indicates one beat. So, in (4, 8) time, a bar would be filled if we have four \(\frac{1}{8}\) th notes.

  • allowed_note_values (default: None) – A list or array containing the allowed note values. A note value of 1/2 means a half note, a note value of 1/4 means a quarternote etc. Defaults to [1/4, 1/8, 1/16].

  • n_rests (default: 0) – If desired, one can provide a number of rests to be inserted at random locations. These are placed after the random selection of note values.

  • rng (default: None) – A numpy.random.Generator object. If not supplied numpy.random.default_rng() is used.

  • name (default: None) – If desired, one can give a rhythm a name. This is for instance used when printing the rhythm, or when plotting the rhythm. It can always be retrieved and changed via Rhythm.name.

Examples

>>> import numpy as np  # not required, here for reproducability
>>> generator = np.random.default_rng(seed=321)  # not required, for reproducability
>>> r = Rhythm.generate_random_rhythm(rng=generator)
>>> print(r.iois)
[125. 250. 125. 125. 500. 125. 125. 125. 500.]
>>> import numpy as np  # not required, here for reproducability
>>> generator = np.random.default_rng(seed=321)  # not required, here for reproducability
>>> r = Rhythm.generate_random_rhythm(beat_ms=1000, allowed_note_values=[1/2, 1/4, 1/8], rng=generator)
>>> print(r.iois)
[ 500. 1000.  500.  500. 1000.  500.]
property integer_ratios: ndarray#

Calculate how to describe the rhythm in integer ratio numerators from the total duration of the sequence by finding the least common multiplier.

Example

A sequence of IOIs [250, 500, 1000, 250] has a total duration of 2000 ms. This can be described using the least common multiplier as \(\frac{1}{8}, \frac{2}{8}, \frac{4}{8}, \frac{1}{8}\), so this method returns the numerators [1, 2, 4, 1].

Notes

The method for calculating the integer ratios is based on Jacoby and McDermott [JM17].

Caution

This function uses rounding to find the nearest integer ratio.

Examples

>>> r = Rhythm([250, 500, 1000, 250])
>>> print(r.integer_ratios)
[1 2 4 1]
property iois: ndarray#
property mean_ioi: float64#

The average inter-onset interval (IOI).

property median_ioi: float64#

The median inter-onset interval (IOI).

property note_values#

This property returns the denominators of the note values in this sequence, calculated from the inter-onset intervals (IOIs). A note value of 1/2 means a half note. A note value of 1/4 means a quarternote, etc. Three triplet eighth notes would be [1/12, 1/12, 1/12].

Caution

Please note that this function is basic (e.g. there is no support for dotted notes etc.). That’s beyond the scope of this package.

Examples

>>> r = Rhythm([500, 1000, 250, 250], time_signature=(4, 4), beat_ms=500)
>>> print(r.note_values)
[Fraction(1, 4), Fraction(1, 2), Fraction(1, 8), Fraction(1, 8)]
>>> r = Rhythm([166.66666667, 166.66666667, 166.66666667, 500, 500, 500], beat_ms=500)
>>> print(r.note_values)
[Fraction(1, 12), Fraction(1, 12), Fraction(1, 12), Fraction(1, 4), Fraction(1, 4), Fraction(1, 4)]
property onsets: ndarray#

Returns the event onsets (t values) on the basis of the sequence objects’ inter-onset intervals (IOIs).

plot_rhythm(filepath=None, staff_type='rhythm', print_staff=True, title=None, figsize=None, dpi=600, ax=None)[source]#

Make a plot containing the musical notation of the rhythm. This function requires an installation of ‘abjad’ and ‘lilypond’. You can install both through pip install 'thebeat[music-notation]'. For more details, see https://thebeat.readthedocs.io/en/latest/installation.html.

The plot is returned as a matplotlib.figure.Figure and matplotlib.axes.Axes object, which you can manipulate.

../../_images/plot_rhythm_rhythmstaff.png

A plot with the default print_staff=True and the default staff_type="rhythm".#

../../_images/plot_rhythm_withstaff.png

A plot with the default print_staff=True and staff_type="percussion".#

../../_images/plot_rhythm_nostaff.png

A plot with print_staff=False.#

Parameters:
  • filepath (PathLike | str, default: None) – Optionally, you can save the plot to a file. Supported file formats are only ‘.png’ and ‘.pdf’. The desired file format will be selected based on what the filepath ends with.

  • staff_type (str, default: 'rhythm') – Either ‘percussion’ or ‘rhythm’. ‘Rhythm’ is a single line (like a woodblock score). Percussion is drum notation.

  • print_staff (bool, default: True) – If desired, you can choose to print a musical staff (the default is not to do this). The staff will be a percussion staff.

  • title (str | None, default: None) – A title for the plot. Note that this is not considered when saving the plot as an .eps file.

  • figsize (tuple[float, float] | None, default: None) – The figure size in inches, as a tuple of floats. This refers to the figsize argument in matplotlib.pyplot.figure().

  • dpi (int, default: 600) – The resolution of the plot in dots per inch.

  • ax (Axes | None, default: None) – Optionally, you can provide an existing matplotlib.axes.Axes object to plot the rhythm on.

Return type:

tuple[Figure, Axes]

Examples

>>> r = Rhythm([500, 250, 1000, 250], beat_ms=500)
>>> r.plot_rhythm()
>>> r = Rhythm([250, 250, 500, 500, 1500], time_signature=(3, 4))
>>> fig, ax = r.plot_rhythm(print_staff=True)
>>> plt.show()
>>> r = Rhythm.from_note_values([1/4, 1/4, 1/4, 1/4])
>>> r.plot_rhythm(filepath='isochronous_rhythm.pdf')
to_sequence()[source]#

Convert the rhythm to a Sequence object.

Return type:

Sequence