pyriodic package#

Submodules#

pyriodic.circular#

class pyriodic.circular.Circular(data: ndarray, labels: list | ndarray | None = None, unit: str = 'radians', full_range: int | None = None)#

Bases: object

A class for representing and working with circular data (e.g., angles, time-of-day, phase).

This class supports circular statistics and visualization of data that wraps around a fixed range, such as angles (in radians or degrees), phases, hours, or other cyclic measurements. It provides basic unit validation, conversion between degrees and radians, and visualisation tools.

Parameters:
  • data (array-like) – A sequence of numerical values representing circular measurements. Values should be in the range appropriate to the specified unit.

  • labels (array-like of str or int, optional) – Optional condition labels or identifiers corresponding to each data point.

  • unit (str, optional) – The unit of the input data. Must be one of {“radians”, “degrees”}. Default is “radians”. Assumes radian range to be from 0 to 2pi.

  • full_range (int, optional)

data#

The circular data as a NumPy array.

Type:

ndarray

labels#

Optional labels (e.g., condition tags) for each data point.

Type:

ndarray or list

unit#

Unit of measurement, either “radians” or “degrees”.

Type:

str

classmethod from_multiple(circular_objects, labels=None)#
mean(group_by_label: bool = False)#
plot(ax=None, histogram=False, group_by_labels=False)#
r()#

pyriodic.desc#

pyriodic.desc.angular_deviation(rad: ndarray)#
pyriodic.desc.circular_mean(rad: ndarray, wrap_to_2pi: bool = True)#

Compute the mean angle from a list of angles in radians.

Parameters:#

radnp.ndarray

Array of angles in radians.

wrap_to_2pibool, default=True

If True, wraps result to range [0, 2π]. If False, result is in [-π, π].

Returns:#

meanfloat

The circular mean angle.

pyriodic.desc.circular_r(rad: ndarray)#

Compute the length of the mean resultant vector ( r ), a measure of circular concentration.

\[r = \sqrt{\bar{C}^2 + \bar{S}^2}\]
pyriodic.desc.circular_standard_deviation(rad: ndarray)#

pyriodic.phase_events#

class pyriodic.phase_events.PhaseEvents(phase_dict: dict)#

Bases: object

mean()#
plot(histogram: ndarray | None = None, savepath: Path | str | None = None)#
r()#
to_circular(include: str | list[str])#
pyriodic.phase_events.compute_segment_outliers(segments, threshold=3, sampling_rate=None)#

Identify segment durations that deviate > threshold * SD from the mean. Optionally normalize by sampling_rate.

pyriodic.phase_events.create_phase_events(phase_ts: ndarray, events: ndarray, event_labels: ndarray | None = None, unit: str = 'radians', first_samp: int = 0, rejection_method: str | None = None, rejection_criterion: float | None = None, return_rejected: bool = False) PhaseEvents | tuple[PhaseEvents, list[int]]#

Create Circular object(s) from a phase angle time series and event markers. Optionally apply cycle-based rejection criteria to exclude events occurring during atypical phase dynamics.

Parameters:
  • phase_ts (np.ndarray) – 1D array of phase values (in radians), typically spanning multiple 0–2π cycles.

  • events (np.ndarray) – 1D array of sample indices at which to extract phase values.

  • event_labels (np.ndarray, optional) – Labels for grouping events. If None, returns a single Circular object; otherwise, returns a PhaseEvents container grouped by unique labels.

  • unit (str) – Unit of the input phase time series and the desired unit for output Circular objects. Must be either ‘radians’ or ‘degrees’. Internally, all computations are performed in radians.

  • first_samp (int) – Offset to subtract from each event index to align with the phase time series (useful if phase_ts is a segment of a longer recording).

  • rejection_method (str, optional) –

    Method to reject events based on surrounding phase dynamics. Currently supported:

    • ’segment_duration_sd’ : excludes events occurring during rising or falling phase segments whose durations deviate more than rejection_criterion standard deviations from the mean across cycles.

  • rejection_criterion (float, optional) – Threshold (in standard deviation units) for identifying outlier segments. Only used if rejection_method=’segment_duration_sd’. Default is 3.

  • return_rejected (bool) – If True, also return a list of rejected event indices.

Returns:

  • Circular or PhaseEvents – If event_labels is None, returns a single Circular object. Otherwise, returns a PhaseEvents object containing condition-grouped Circular data.

  • (optional) list[int] – If return_rejected is True, returns a second value: the list of event indices that were rejected.

pyriodic.phase_events.get_outlier_sample_indices(segments, outlier_indices)#

Convert outlier segments to a flat set of sample indices for fast lookup.

pyriodic.phase_events.get_phase_segments(phase_ts: ndarray)#

Identify rising (0→π) and falling (π→2π) phase segments in a wrapped phase signal.

Parameters:

phase_ts (np.ndarray) – 1D array of phase values (in radians), assumed to evolve continuously over time.

Returns:

  • rising_segments (list of (start_idx, stop_idx)) – List of index tuples for rising phase segments (0 to π).

  • falling_segments (list of (start_idx, stop_idx)) – List of index tuples for falling phase segments (π to 2π).

pyriodic.preproc module#

class pyriodic.preproc.RawSignal(data, fs, info=None)#

Bases: object

copy()#
filter_bandpass(low, high)#
property history#
interpolate_missing()#
phase_hilbert()#

Extract instantaneous phase angle using the Hilbert Transform.

Parameters:

ts (np.ndarray) – 1D time series

Returns:

phase angles in radians (0 to 2π)

Return type:

np.ndarray

phase_linear(peak_finder=None, distance=100, prominence=0.01)#

Extract phase using linear interpolation between peaks and troughs at

Parameters:
  • peak_finder (callable) – Optional custom function(ts, **kwargs) -> np.ndarray of peak indices.

  • distance (int) – Minimum distance between peaks.

  • prominence (float) – Prominence threshold for peak detection.

Returns:

phase peaks troughs

phase_onepoint(peak_finder=None, distance=100, prominence=0.01)#

Extract phase using linear interpolation between from 0 to 2pi between peaks.

Parameters:
  • peak_finder (callable) – Optional custom function(ts, **kwargs) -> np.ndarray of peak indices.

  • distance (int) – Minimum distance between peaks.

  • prominence (float) – Prominence threshold for peak detection.

Returns:

phase peaks

phase_threepoint(peak_finder: Callable[[...], ndarray] | None = None, distance: int = 100, prominence: float | int = 0.01, percentile: float | int = 50, descent_window: int = 5)#

Extract phase using a three-point method: Peak → descending slope → flat region → ascending slope → next peak.

Parameters:
  • peak_finder (callable) – Optional function(ts, **kwargs) → np.ndarray of peak indices.

  • distance (int) – Min distance between peaks (used if no custom peak_finder).

  • prominence (float) – Prominence threshold for peak detection.

  • percentile (float) – Percentile of absolute gradient below which region is considered ‘flat’.

  • descent_window (int) – Number of samples used to confirm descent/ascent before/after flat region.

Returns:

Phase array in radians (0 to 2π) peaks (np.ndarray): Indices of detected peaks troughs (list of tuples): List of (trough_start, trough_end) for flat segments

Return type:

phase (np.ndarray)

remove_outliers(threshold=2.5, linear_interpolation=True)#

Removes outliers …. threshold + linear interpolation

zscore()#

Normalises the signal in-place to mean 0 and unit variance.

pyriodic.stats module#

pyriodic.stats.angular_randomisation_test(a: Circular, b: Circular)#

This function performs the angular randomisation test for homogeneity of 2 groups

https://ijnaa.semnan.ac.ir/article_5992_e5a258374dedcbb40d792b81bfc94591.pdf

H0: the samples come from the same population HA: the samples do not come from the same population

pyriodic.stats.kuiper_test(a: Circular)#

Perform Kuiper’s test for uniformity on circular data.

Parameters:
  • a (Circular) – An instance of the Circular class containing the data to test.

  • return_stat (bool) – If True, return the test statistic in addition to the p-value.

Returns:

  • p_value (float) – The p-value for the test.

  • stat (float) – The Kuiper test statistic.

pyriodic.utils module#

pyriodic.utils.dat2rad(data: ndarray | float | int, full_range: float | int = 360)#
pyriodic.utils.rad2dat(rad: ndarray | float | int, full_range: float | int = 360)#

pyriodic.viz#

class pyriodic.viz.CircPlot(circ: Circular, group_by_labels: bool = True, colours=None, fig_size=(6, 6), dpi=300, ax=None, ylim=None)#

Bases: object

add_circular_mean(grouped: bool | None = None, **kwargs)#

Plot mean resultant vector(s) as arrows.

Parameters:
  • grouped (bool, optional) – If None, uses self.group_by_labels. If True, plots a vector per label. If False, plots a single mean vector for all data.

  • kwargs (dict) – Additional keyword arguments passed to ax.arrow. Common kwargs: width, color, alpha, linewidth.

add_density(kappa=20, n_bins=500, grouped: bool | None = None, **kwargs)#

Add a circular density estimate using Von Mises KDE.

Parameters:
  • kappa (float) – Concentration parameter of the Von Mises distribution (higher = sharper).

  • n_bins (int) – Number of angular bins to evaluate the density on.

  • grouped (bool, optional) – If None, uses self.group_by_labels. If True, plots a density curve for each label separately. If False, plots a single joint density curve for all data.

  • kwargs (dict) – Additional keyword arguments passed to ax.plot (e.g., linewidth, linestyle, alpha).

add_histogram(data: dict[str, ndarray] | ndarray | None = None, bins=36, alpha=0.2, color: str = 'grey')#

Plot histogram as radial bars on the polar axis. If data is None, uses circular data in self.circs.

Parameters: - data: Optional dict[label] = array or a single array. - bins: Number of angular bins (default 36). - alpha: Transparency of bars.

add_legend(location='upper right', **kwargs)#

Add a legend to the plot.

Parameters:
  • location (str) – Position of the legend (default is ‘upper right’).

  • kwargs (dict) – Additional arguments passed to ax.legend().

add_points(grouped: bool | None = None, **kwargs)#

Plot circular data points on the polar axis.

Parameters:
  • grouped (bool, optional) – If None, uses the self.group_by_labels setting. If True, plots each label separately. If False, plots all data points together, ignoring labels.

  • kwargs (dict) – Additional keyword arguments passed to ax.scatter, such as s, alpha, or marker.

prepare_ax(ylim)#
save(filename, **kwargs)#

Save the figure to a file

show()#
pyriodic.viz.plot_phase_diagnostics(phase_angles: dict[str, ndarray], fs: int | float, data: ndarray | None = None, events: list | ndarray | None = None, event_labels: list | ndarray | None = None, peaks=None, troughs=None, flat_start_stop=None, savepath=None, figsize=None, interactive: bool = False, window_duration: float = 20.0)#
Parameters:
  • phase_angles (dict[str, np.ndarray]) – Dictionary of named phase angle signals (e.g., {“3-point”: …, “Hilbert”: …}). Each should be 1D array of same length as data.

  • fs (float) – Sampling frequency (Hz).

  • data (np.ndarray, optional) – Raw or preprocessed time series signal (same length as phase arrays).

  • events (list[int] or np.ndarray, optional) – Sample indices of events to mark (e.g., stimulus or response times).

  • event_labels (list[str], optional) – Label for each event (same length as events). Used for color grouping.

  • peaks (list[int] or np.ndarray, optional) – Sample indices of identified peaks.

  • troughs (list[int] or np.ndarray, optional) – Sample indices of identified troughs.

  • flat_start_stop (list[tuple[int, int]] or list[int], optional) – Flat segments as start–stop index tuples or flat indices directly.

  • savepath (str or Path, optional) – If provided, saves static plot to this location (only applies if interactive=False).

  • figsize (tuple[int, int], optional) – Size of the figure in inches (only applies if interactive=False).

  • interactive (bool) – If True, launches an interactive slider-based window viewer (Matplotlib).

  • window_duration (float) – Duration (in seconds) of each visible window in interactive mode.

Returns:

  • fig (matplotlib.figure.Figure) – The created figure.

  • axes (list[matplotlib.axes.Axes]) – The axes used in the plot (one per row: signal + phase tracks).

pyriodic.viz.vonmises_kde(data, kappa, min_x=0, max_x=6.283185307179586, n_bins=100)#