Pulse¶
Auto-generated documentation for musicalgestures._pulse module.
Pulse and cycle segmentation for accelerating rhythmic sequences.
- Mgt-python / Modules / Musicalgestures / Pulse
Tools for grouping event onsets (e.g. drum strokes) into per-cycle stroke groups, tabulating per-cycle metrics, fitting an exponential accelerando model, and detecting motion onsets from a quantity-of-motion signal.
These helpers are independent of the MgVideo/MgAudio classes and operate on plain numpy arrays of onset times or 1-D motion signals.
Source: ro study (Jensenius) -- analysis of the accelerating ro ritual's drum-stroke cycles and their coupling to body motion.
Cycle¶
One rhythmic cycle: a group of stroke onsets plus an optional secondary event (e.g. a shout) that falls inside the cycle.
Source: ro study (Jensenius).
Attributes¶
indexint - Zero-based cycle index.strokeslist - Onset times (s) of the strokes in this cycle. event (float | None): Time (s) of the cycle's secondary event, or None.
Cycle().n_strokes¶
int: Number of strokes in the cycle.
Cycle().stroke_gap¶
float: Gap (s) between the first two strokes (NaN if fewer than 2).
Cycle().t_start¶
float: Time (s) of the cycle's first stroke.
cycle_table¶
Tabulate per-cycle metrics from a list of Cycle objects.
Source: ro study (Jensenius).
Arguments¶
cycleslist - A list of Cycle objects (see segment_cycles).clip_idstr, optional - Identifier written to theclipcolumn. Defaults to "".contextstr, optional - Label written to thecontextcolumn. Defaults to "".
Returns¶
pd.DataFrame- One row per cycle with columnsclip,context,cycle,t(cycle start, s),ioi(to next cycle start, s),n_strokes,stroke_gap(s),event(secondary-event time, s or NaN) andstroke_event_ioi(event minus cycle start, s or NaN).
fit_accelerando¶
Fit an exponential accelerando model IOI(t) = ioi0 * 2**(-t / t_double)
via least squares on log2(IOI): t_double is the time (s) it takes the
inter-onset interval to halve (i.e. the tempo to double).
Source: ro study (Jensenius).
Arguments¶
timesnp.ndarray - Cycle start times in seconds.ioisnp.ndarray - Inter-onset intervals (s) at those times. Non-finite or non-positive entries are ignored.
Returns¶
tuple-(ioi0, t_double, r2)whereioi0is the fitted IOI at t=0 (s),t_doubleis the tempo-doubling time (s;np.infif the sequence is not accelerating), andr2is the fit's coefficient of determination on log2(IOI). Degenerate input -- fewer than 3 valid (finite, strictly positive) IOI points, too few to constrain the 2-parameterfit- returns(nan, nan, nan).
group_strokes¶
def group_strokes(
onset_times,
max_strokes=4,
gap_lo=0.1,
gap_hi=0.6,
w_abs=6.0,
w_within=4.0,
tol_within=0.15,
w_order=2.5,
w_trend=2.0,
tol_trend=0.25,
size_costs=(1.0, 0.0, 1.5, 6.0),
):
Segment stroke onsets into per-cycle stroke groups by dynamic programming over candidate group boundaries (Viterbi over segmentations), with a greedily carried stroke-gap estimate (EMA) that is exact given that carried estimate but is not itself part of the DP state key, so Bellman optimality does not strictly hold over the full segmentation.
The cost of a segmentation encodes structural priors for an accelerating cyclic pattern (developed for the ro ritual's double drum strokes):
- size prior --
size_costs[k-1]per k-stroke group: with the defaults, double strokes are free, singles/triples carry a small penalty, >=4 a steep one; - within-gap plausibility -- gaps inside a group should fall in
[gap_lo, gap_hi]seconds (w_absx log-excess outside) and stay close to a running stroke-gap estimate (EMA, weight 0.5):w_withinx |log-ratio| beyondtol_within; - ordering prior -- a between-group gap shorter than the current
stroke-gap estimate costs
w_orderx the log-ratio shortfall; - accelerando prior -- successive between-group gaps should not grow:
an increase beyond
tol_trend(log) costsw_trendx the excess (decreases are free, so a climax's shrinking gaps cost nothing).
Unlike a single running threshold, the trend and ordering terms let the decision boundary between stroke gaps and cycle gaps shrink with the accelerando, so the climax stays resolved even when the cycle gap drops to (or just below) the stroke gap in the final cycles.
Source: ro study (Jensenius).
Arguments¶
onset_timesnp.ndarray - Stroke onset times in seconds (any order).max_strokesint, optional - Maximum strokes per group. Defaults to 4.gap_lofloat, optional - Lower bound (s) of plausible within-group gaps. Defaults to 0.10.gap_hifloat, optional - Upper bound (s) of plausible within-group gaps. Defaults to 0.60.w_absfloat, optional - Weight of the absolute within-gap plausibility term. Defaults to 6.0.w_withinfloat, optional - Weight of the within-gap-vs-EMA term. Defaults to 4.0.tol_withinfloat, optional - Log-ratio tolerance of the within-gap-vs-EMA term. Defaults to 0.15.w_orderfloat, optional - Weight of the ordering prior. Defaults to 2.5.w_trendfloat, optional - Weight of the accelerando (non-increasing gaps) prior. Defaults to 2.0.tol_trendfloat, optional - Log-ratio tolerance of the accelerando prior. Defaults to 0.25.size_coststuple, optional - Cost per group of size 1, 2, 3, >=4. Defaults to (1.0, 0.0, 1.5, 6.0).
Returns¶
list- A list of groups, each a list of stroke onset times (floats, seconds).
motion_onsets¶
Times of the steepest sustained rises in a motion signal (e.g. a
quantity-of-motion curve): the signal is low-pass filtered, its positive
time-derivative is formed, and peaks of that derivative are picked with
the canonical peak-picker (musicalgestures.pick_peaks) using a robust
prominence gate of 0.25 x (99th percentile - median) of the derivative.
Source: ro study (Jensenius) -- motion onsets of the rowing gesture,
related to the drum cycles via per_cycle_motion_delta.
Arguments¶
motionnp.ndarray - 1-D motion signal (e.g. mean absolute frame difference).fsfloat - Sampling rate of the signal (Hz, e.g. video frames per second).min_intervalfloat, optional - Minimum interval between onsets (s). Defaults to 0.25.smooth_cutofffloat, optional - Low-pass cutoff (Hz) applied before differentiation. Defaults to 8.0.
Returns¶
np.ndarray- Onset times in seconds.
segment_cycles¶
Segment stroke onsets into Cycle objects: one Cycle per stroke group (see group_strokes); the cycle's secondary event is the first event onset in [group start, next group start).
Source: ro study (Jensenius) -- the secondary events were the ritual's shouts.
Arguments¶
onset_timesnp.ndarray - Stroke onset times in seconds.event_timesnp.ndarray, optional - Onset times (s) of a secondary event stream (e.g. shouts) to assign to cycles. Defaults to None.**kwargs- Passed on to group_strokes.
Returns¶
list- A list of Cycle objects.