rhythmic_segments.patterns

Pattern generation utilities for rhythmic segments.

Attributes

Functions

product_patterns(→ Tuple[numpy.ndarray, numpy.ndarray])

Return all possible patterns that can be generated using combinations

integer_ratio_patterns(→ Tuple[numpy.ndarray, ...)

Convenience wrapper for product_patterns().

isochronous_pattern(→ numpy.ndarray)

Return the isochronous pattern of given length.

total_variation_distance(→ numpy.ndarray)

Return the pairwise total variation distance between patterns.

anisochrony(→ Union[float, numpy.ndarray])

Return the anisochrony of a given pattern.

isochrony(→ Union[float, numpy.ndarray])

Return the normalized isochrony score for the given pattern(s).

npvi(→ float)

Return the normalized pairwise variability index for length-two patterns.

Module Contents

rhythmic_segments.patterns.PatternsMatrixLike
rhythmic_segments.patterns.PatternsLike
rhythmic_segments.patterns.product_patterns(factors: Iterable[int], length: int) Tuple[numpy.ndarray, numpy.ndarray]
Return all possible patterns that can be generated using combinations

of factors of given length.

A pattern is a length-length vector whose elements are normalized to sum to one. The accompanying ratios matrix stores the raw integer combinations.

>>> patterns, ratios = product_patterns([1, 2], 2)
>>> patterns
array([[0.5       , 0.5       ],
       [0.33333333, 0.66666667],
       [0.66666667, 0.33333333]])
>>> ratios
array([[1, 1],
       [1, 2],
       [2, 1]])
rhythmic_segments.patterns.integer_ratio_patterns(integers: Iterable[int], length: int) Tuple[numpy.ndarray, numpy.ndarray]

Convenience wrapper for product_patterns().

>>> integer_ratio_patterns([1, 2], 2)[0]
array([[0.5       , 0.5       ],
       [0.33333333, 0.66666667],
       [0.66666667, 0.33333333]])
rhythmic_segments.patterns.isochronous_pattern(length: int) numpy.ndarray

Return the isochronous pattern of given length.

>>> isochronous_pattern(4)
array([[0.25, 0.25, 0.25, 0.25]])
rhythmic_segments.patterns.total_variation_distance(pat1: PatternsLike, pat2: PatternsLike, check_normalized: bool = True, assume_normalized_tol: float = 1e-09) numpy.ndarray

Return the pairwise total variation distance between patterns.

The function accepts one-dimensional patterns (single observations) as well as two-dimensional arrays where each row represents a pattern. In either case, the return value is a distance matrix whose (i, j) entry contains the distance between pat1[i] and pat2[j].

>>> total_variation_distance([0.5, 0.5], [0.5, 0.5])
array([[0.]])
>>> total_variation_distance([0.5, 0.5], [1.0, 0.0])
array([[0.5]])
>>> total_variation_distance([[0.25, 0.5, 0.25]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
array([[0.75, 0.5 ]])
rhythmic_segments.patterns.anisochrony(patterns: PatternsLike, check_normalized=True) float | numpy.ndarray

Return the anisochrony of a given pattern.

The anisochrony is the normalized total variation distance between the given pattern and the isochronous pattern of the same length. The normalization constant ensures the anisochrony is in the range [0, 1].

>>> anisochrony([0.5, 0.5])
0.0
>>> anisochrony([[0.25, 0.75], [0.2, 0.8]])
array([0.5, 0.6])
>>> anisochrony([0.25, 0.5, 0.25])
0.25
rhythmic_segments.patterns.isochrony(patterns: PatternsLike, check_normalized=True) float | numpy.ndarray

Return the normalized isochrony score for the given pattern(s).

Isochrony is defined as \(1 - \text{anisochrony}\). Perfectly regular rhythms yield a score of 1 and increasingly irregular (un-isochronous) patterns approach 0. As with anisochrony(), a single pattern produces a scalar while multiple patterns return a NumPy array of scores.

>>> isochrony([0.5, 0.5])
1.0
>>> isochrony([[0.25, 0.75], [0.5, 0.5]])
array([0.5, 1. ])
rhythmic_segments.patterns.npvi(patterns: PatternsMatrixLike, check_normalized: bool = True) float

Return the normalized pairwise variability index for length-two patterns.

Each input pattern should contain exactly two values (e.g., consecutive intervals). The input must contain one pattern per row. When check_normalized is True (default) the patterns must sum to one, which is typical for normalized segment durations. The function returns the mean nPVI across all provided patterns.

>>> npvi([[0.25, 0.75], [0.5, 0.5]])
50.0
>>> npvi([[1.0, 0.0], [0.0, 1.0]])
200.0
>>> npvi([[0.5, 0.5], [0.5, 0.5], [0.5, 0.5]])
0.0