Sequence class#

Arguably, this is the most important class in the package. How to construct it, and how to use its methods is illustrated below:

class thebeat.core.Sequence(iois, first_onset=0.0, end_with_interval=False, name=None)[source]#

Arguably, the Sequence class is the most important class in this package. It is used as the basis for many functions as it contains timing information in the form of inter-onset intervals (IOIs; the times between the onset of an event, and the onset of the next event) and event onsets (i.e. t values). IOIs are what we use to construct Sequence objects.

The most basic way of constructing a Sequence object is by passing it a list or array of IOIs (see under __init__()). However, the different class methods (e.g. Sequence.generate_isochronous()) may also be used.

For the Sequence class it does not matter whether the provided IOIs are in seconds or milliseconds. However, it does matter when passing the Sequence object to e.g. a SoundSequence object (see SoundSequence.__init__()).

This class additionally contains methods and attributes to, for instance, change the tempo, add Gaussian noise, or to plot the Sequence object using matplotlib.

For more info, check out the __init__() method, and the different methods below.

__init__(iois, first_onset=0.0, end_with_interval=False, name=None)[source]#

Construct a Sequence class on the basis of inter-onset intervals (IOIs). When end_with_interval is False (the default), the sequence contains n event onsets, but n-1 IOIs. If True, the sequence contains an equal number of event onsets and IOIs.

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

  • end_with_interval (default: False) – Indicates whether sequence has an extra final inter-onset interval; this is useful for musical/rhythmical sequences.

  • 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 BaseSequence.name.

Examples

>>> iois = [500, 400, 600, 400]
>>> seq = Sequence(iois)
>>> print(seq.onsets)
[   0.  500.  900. 1500. 1900.]
add_noise_gaussian(noise_sd, rng=None)[source]#

This method can be used to add some Gaussian noise to the inter-onset intervals (IOIs) of the Sequence object. It uses a normal distribution with mean 0, and a standard deviation of noise_sd.

Parameters:

Examples

>>> gen = np.random.default_rng(seed=123)
>>> seq = Sequence.generate_isochronous(n_events=5,ioi=500)
>>> print(seq.iois)
[500. 500. 500. 500.]
>>> seq.add_noise_gaussian(noise_sd=50, rng=gen)
>>> print(seq.iois)
[450.54393248 481.61066743 564.39626306 509.69872096]
>>> print(seq.onsets)
[   0.          450.54393248  932.15459991 1496.55086297 2006.24958393]
change_tempo(factor)[source]#

Change the tempo of the Sequence object, where a factor of 1 or bigger increases the tempo (resulting in smaller inter-onset intervals). A factor between 0 and 1 decreases the tempo (resulting in larger inter-onset intervals).

Parameters:

factor (float) – Tempo change factor. E.g. 2 means twice as fast. 0.5 means twice as slow.

Return type:

None

Examples

>>> seq = Sequence.generate_isochronous(n_events=5, ioi=500)
>>> print(seq.onsets)
[   0.  500. 1000. 1500. 2000.]
>>> seq.change_tempo(2)
>>> print(seq.onsets)
[   0.  250.  500.  750. 1000.]
change_tempo_linearly(total_change)[source]#

Create a ritardando or accelerando effect in the inter-onset intervals (IOIs). It divides the IOIs by a vector linearly spaced between 1 and total_change.

Parameters:

total_change (float) – Total tempo change at the end of the Sequence compared to the beginning. So, a total change of 2 (accelerando) results in a final IOI that is twice as short as the first IOI. A total change of 0.5 (ritardando) results in a final IOI that is twice as long as the first IOI.

Examples

>>> seq = Sequence.generate_isochronous(n_events=5,ioi=500)
>>> print(seq.iois)
[500. 500. 500. 500.]
>>> seq.change_tempo_linearly(total_change=2)
>>> print(seq.iois)
[500. 375. 300. 250.]
copy(deep=True)#

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_binary_string(pattern, grid_ioi, **kwargs)[source]#

This class method can be used to construct a new Sequence object on the basis of a binary string. The binary string is interpreted as a sequence of 0s and 1s, where 0 represents silence and 1 represents an event onset. The grid_ioi represents the duration of one digit.

Parameters:
  • string – The binary string. For instance: '10101100'.

  • grid_ioi (float) – The duration of one digit in the binary string. For instance: 250.

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor (see thebeat.core.Sequence.__init__()).

Return type:

Sequence

Examples

>>> seq = Sequence.from_binary_string('10101100', 250)
>>> print(seq.iois)
[500. 500. 250. 750.]
classmethod from_integer_ratios(numerators, value_of_one, **kwargs)[source]#

This class method can be used to construct a new Sequence object on the basis of integer ratios. See Sequence.integer_ratios for explanation.

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

  • value_of_one – This represents the duration of the 1, multiples of this value are used. For instance, a sequence of [2, 4] using value_of_one=500 would be a Sequence with IOIs: [1000 2000].

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor (see thebeat.core.Sequence.__init__().

Examples

>>> seq = Sequence.from_integer_ratios(numerators=[1, 2, 4], value_of_one=500)
>>> print(seq.iois)
[ 500. 1000. 2000.]
classmethod from_onsets(onsets, **kwargs)[source]#

Class method that can be used to generate a new Sequence object on the basis of event onsets. Here, the onsets do not have to start with zero.

Parameters:
  • onsets (ndarray[float] | list[float]) – An array or list containg event onsets, for instance: [0, 500, 1000]. The onsets do not have to start with zero.

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor (excluding first_onset and end_with_interval, which are set by this method).

Return type:

Sequence

Examples

>>> seq = Sequence.from_onsets([0, 500, 1000])
>>> print(seq.iois)
[500. 500.]
classmethod from_txt(filepath, type='iois', end_with_interval=False, **kwargs)[source]#

Class method that can be used to generate a new Sequence object from a text file.

The text file is assumed to contain one IOI/onset per line.

Parameters:
  • filepath (str | Path) – The path to the text file.

  • type (str, default: 'iois') – The type of the sequence. Can be either iois or onsets.

  • end_with_interval (bool, default: False) – Indicates whether the sequence should end with an event (False) or an interval (True).

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor.

Return type:

Sequence

classmethod generate_isochronous(n_events, ioi, end_with_interval=False, **kwargs)[source]#

Class method that generates a sequence of isochronous (i.e. equidistant) inter-onset intervals. Note that there will be n-1 IOIs in a sequence. IOIs are rounded off to integers.

Parameters:
  • n_events (int) – The desired number of events in the sequence.

  • ioi (float) – The inter-onset interval to be used between all events.

  • end_with_interval (bool, default: False) – Indicates whether the sequence should end with an event (False) or an interval (True).

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor.

Return type:

Sequence

Examples

>>> seq = Sequence.generate_isochronous(n_events=5,ioi=500)
>>> print(seq.iois)
[500. 500. 500. 500.]
>>> print(len(seq.onsets))
5
>>> print(len(seq.iois))
4
>>> seq = Sequence.generate_isochronous(n_events=5,ioi=500,end_with_interval=True)
>>> print(len(seq.onsets))
5
>>> print(len(seq.iois))
5
classmethod generate_random_exponential(n_events, lam, rng=None, end_with_interval=False, **kwargs)[source]#

Class method that generates a Sequence object with random inter-onset intervals (IOIs) based on an exponential distribution.

Parameters:
  • n_events (int) – The desired number of events in the sequence.

  • lam (float) – The desired value for lambda.

  • rng (Optional[Generator], default: None) – A numpy.random.Generator object. If not supplied NumPy’s numpy.random.default_rng() is used.

  • end_with_interval (bool, default: False) – Indicates whether the sequence should end with an event (False) or an interval (True).

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor.

Return type:

Sequence

Examples

>>> generator = np.random.default_rng(seed=123)
>>> seq = Sequence.generate_random_exponential(n_events=5,lam=500,rng=generator)
>>> print(seq.iois)
[298.48624756  58.51553052 125.89734975 153.98272273]
classmethod generate_random_normal(n_events, mu, sigma, rng=None, end_with_interval=False, **kwargs)[source]#

Class method that generates a Sequence object with random inter-onset intervals (IOIs) based on the normal distribution.

Parameters:
  • n_events (int) – The desired number of events in the sequence.

  • mu (float) – The mean of the normal distribution.

  • sigma (float) – The standard deviation of the normal distribution.

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

  • end_with_interval (bool, default: False) – Indicates whether the sequence should end with an event (False) or an interval (True).

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor.

Return type:

Sequence

Examples

>>> generator = np.random.default_rng(seed=123)
>>> seq = Sequence.generate_random_normal(n_events=5,mu=500,sigma=50,rng=generator)
>>> print(seq.iois)
[450.54393248 481.61066743 564.39626306 509.69872096]
>>> seq = Sequence.generate_random_normal(n_events=5,mu=500,sigma=50,end_with_interval=True)
>>> len(seq.onsets) == len(seq.iois)
True
classmethod generate_random_poisson(n_events, lam, rng=None, end_with_interval=False, **kwargs)[source]#

Class method that generates a Sequence object with random inter-onset intervals (IOIs) based on a Poisson distribution.

Parameters:
  • n_events (int) – The desired number of events in the sequence.

  • lam (float) – The desired value for lambda.

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

  • end_with_interval (bool, default: False) – Indicates whether the sequence should end with an event (False) or an interval (True).

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor.

Return type:

Sequence

Examples

>>> generator = np.random.default_rng(123)
>>> seq = Sequence.generate_random_poisson(n_events=5,lam=500,rng=generator)
>>> print(seq.iois)
[512. 480. 476. 539.]
classmethod generate_random_uniform(n_events, a, b, rng=None, end_with_interval=False, **kwargs)[source]#

Class method that generates a Sequence object with random inter-onset intervals (IOIs) based on a uniform distribution.

Parameters:
  • n_events (int) – The desired number of events in the sequence.

  • a (float) – The left bound of the uniform distribution.

  • b (float) – The right bound of the uniform distribution.

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

  • end_with_interval (bool, default: False) – Indicates whether the sequence should end with an event (False) or an interval (True).

  • **kwargs – Additional keyword arguments are passed to the Sequence constructor.

Return type:

Sequence

Examples

>>> generator = np.random.default_rng(seed=123)
>>> seq = Sequence.generate_random_uniform(n_events=5,a=400,b=600,rng=generator)
>>> print(seq.iois)
[536.47037265 410.76420376 444.07197455 436.87436214]
>>> seq = Sequence.generate_random_uniform(n_events=5,a=400,b=600,end_with_interval=True)
>>> len(seq.onsets) == len(seq.iois)
True
property integer_ratios: ndarray#

Calculate how to describe a sequence of IOIs 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. 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].

Examples

>>> seq = Sequence([250, 500, 1000, 250])
>>> print(seq.integer_ratios)
[1 2 4 1]
property interval_ratios_from_dyads: ndarray#

Return sequential interval ratios, calculated as: \(\textrm{ratio}_k = \frac{\textrm{IOI}_k}{\textrm{IOI}_k + \textrm{IOI}_{k+1}}\).

Note that for n IOIs this property returns n-1 ratios.

Notes

The used method is based on the methodology from Roeske et al. [RTPJ20].

Examples

>>> seq = Sequence.from_integer_ratios([2, 2, 1, 1], value_of_one=500)
>>> print(seq.iois)
[1000. 1000.  500.  500.]
>>> print(seq.interval_ratios_from_dyads)
[0.5        0.66666667 0.5       ]
property iois: ndarray#
property mean_ioi: float64#

The average inter-onset interval (IOI).

merge(other)[source]#

Merge this Sequence object with one or multiple other Sequence objects.

Returns a new Sequence object.

Parameters:

other (Sequence | list[Sequence]) – A Sequence object, or a list of Sequence objects.

Returns:

A Sequence object.

Return type:

object

property onsets: ndarray#

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

plot_sequence(linewidth=None, **kwargs)[source]#

Plot the Sequence object as an event plot on the basis of the event onsets.

The lines’ left boundaries are placed at the event onsets.

Parameters:
  • linewidth (default: None) – The desired width of the bars (events). Defaults to 1/10th of the smallest inter-onset interval (IOI). Can be a single value that will be used for each onset, or a list or array of values (i.e with a value for each respective onsets).

  • **kwargs – Additional parameters (e.g. ‘title’, ‘dpi’ etc.) are passed to thebeat.helpers.plot_single_sequence().

Examples

>>> seq = Sequence.generate_isochronous(n_events=5,ioi=500)
>>> seq.plot_sequence()  

In this example, we plot onto an existing Axes object.

>>> import matplotlib.pyplot as plt
>>> seq = Sequence([500, 200, 1000])
>>> fig, axs = plt.subplots(nrows=1, ncols=2)
>>> seq.plot_sequence(ax=axs[0])  
quantize_iois(to)[source]#

Quantize the Sequence object’s IOIs to be multiples of to.

Parameters:

to (float) – The value to be quantized to. E.g. a value of 100 means that the IOIs will be quantized to the nearest multiple of 100.

Examples

>>> seq = Sequence(iois=[235, 510, 420, 99])
>>> print(seq.iois)
[235. 510. 420.  99.]
>>> seq.quantize_iois(to=100)
>>> print(seq.iois)
[200. 500. 400. 100.]
round_onsets(decimals=0)[source]#

Use this function to round off the Sequence object’s onsets (i.e. t values). This can, for instance, be useful to get rid of warnings that are the result of frame rounding. See e.g. SoundSequence.

Note that this function does not return anything. The onsets of the sequence object from which this method is called are rounded.

Parameters:

decimals (int, default: 0) – The number of decimals desired.