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
Rhythmclass 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,Rhythmobjects have musical properties such as a time signature, a beat duration, and they may contain rests.The
Rhythmclass is also used as the basis for aMelody.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
Rhythmobject.- 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 aFraction, 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 viaRhythm.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) – IfTrue, a deep copy is returned. IfFalse, 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 viaRhythm.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.Fractionobjects.- 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 viaRhythm.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_valuesparameter, and then selecting (with replacement)n_barscombinations 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 of1/2means a half note, a note value of1/4means 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) – Anumpy.random.Generatorobject. If not suppliednumpy.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 viaRhythm.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 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/2means a half note. A note value of1/4means 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.Figureandmatplotlib.axes.Axesobject, which you can manipulate.
A plot with the default
print_staff=Trueand the defaultstaff_type="rhythm".#
A plot with the default
print_staff=Trueandstaff_type="percussion".#
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 inmatplotlib.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 existingmatplotlib.axes.Axesobject to plot the rhythm on.
- Return type:
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')