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 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
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.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) [2 4 4 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.
- property fractions: ndarray#
Calculate how to describe the rhythm in fractions from the total duration of the sequence.
Example
A sequence of IOIs
[250, 500, 1000, 250]
has a total duration of 2000 ms. This can be described using the fractions \(\frac{1}{8}, \frac{2}{8}, \frac{4}{8}, \frac{1}{8}\), so this method returns the fractions[1/8, 2/8, 4/8, 1/8]
.Examples
>>> r = Rhythm([250, 500, 1000, 250]) >>> print(r.fractions) [Fraction(1, 8) Fraction(1, 4) Fraction(1, 2) Fraction(1, 8)]
- classmethod from_fractions(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. The fractions can be input either as floats (e.g. 0.25) or as
fractions.Fraction
objects.- Parameters:
fractions – Contains the fractions of the rhythm. For instance:
[1, 2, 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
The fractions represent for each note the proportion of the bar that the note takes up, taking into account the time signature. A few examples:
In 4/4 time, a quarter note would be 1/4, an eighth note 1/8, etc. In 4/8 time, a quarter note would be 1/2, an eighth note 1/4, etc.
In 5/4 time, we would input a quarter note as 1/5, an eighth note as 1/10, etc. In 5/8 time, we would input a dotted quarter note as 3/5, an eighth note as 1/5, etc.
Examples
>>> r = Rhythm.from_fractions([1/4, 1/4, 1/4, 1/4], time_signature=(4, 4), beat_ms=500)
>>> import fractions >>> dotted_halfnote = fractions.Fraction(3, 5) >>> halfnote = fractions.Fraction(2, 5) >>> r = Rhythm.from_fractions([dotted_halfnote, halfnote], time_signature=(5, 4), beat_ms=500)
>>> r = Rhythm.from_fractions([1/4, 1/4, 1/4, 1/4], time_signature=(4, 8), beat_ms=500)
- 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(note_values, time_signature=(4, 4), beat_ms=500, is_played=None, name=None)[source]#
Create a Rhythm object on the basis of note values (i.e. note durations).
Note values are input as the denominators of the fraction. A note value of
2
means a half note, a note value of4
means a quarternote etc. A triplet would be[12, 12, 12]
.- Parameters:
note_values – A list or array containing the denominators of the note values. A note value of
2
means a half note, a note value of4
means a quarternote etc. A triplet would be[12, 12, 12]
.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
.
Examples
>>> r = Rhythm.from_note_values([16, 16, 16, 16, 4, 4, 4], beat_ms=500) >>> print(r.iois) [125. 125. 125. 125. 500. 500. 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_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 denominators of the allowed note values. A note value of2
means a half note, a note value of4
means a quarternote etc. Defaults to[4, 8, 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.Generator
object. 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=[2, 4, 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 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
2
means a half note. A note value of4
means a quarternote, etc. One triplet of three notes would be[12, 12, 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) [4 2 8 8]
>>> r = Rhythm([166.66666667, 166.66666667, 166.66666667, 500, 500, 500], beat_ms=500] >>> print(r.note_values) [12 12 12 4 4 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, suppress_display=False, figsize=None, dpi=600, ax=None)[source]#
Make a plot containing the musical notation of the rhythm. This function requires install ‘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
andmatplotlib.axes.Axes
object, which you can manipulate.- 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 (
Optional
[str
], default:None
) – A title for the plot. Note that this is not considered when saving the plot as an .eps file.suppress_display (
bool
, default:False
) – If desired,you can choose to suppress displaying the plot in your IDE. This means thatmatplotlib.pyplot.show()
is not called. This is useful when you just want to save the plot or use the returnedmatplotlib.figure.Figure
andmatplotlib.axes.Axes
objects.figsize (
Optional
[tuple
[float
,float
]], 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 (
Optional
[Axes
], default:None
) – Optionally, you can provide an existingmatplotlib.axes.Axes
object 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, suppress_display=True) >>> plt.show()
>>> r = Rhythm.from_note_values([4, 4, 4, 4]) >>> r.plot_rhythm(filepath='isochronous_rhythm.pdf')