Source code for pynapple.process.randomize

"""
Functions to shuffle timestamps to create surrogate datasets.
"""

import numpy as np

from .. import core as nap


[docs] def shift_timestamps(ts, min_shift=0.0, max_shift=None): """ Shifts all the time stamps of a random amount between min_shift and max_shift, wrapping the end of the time support to the beginning. Parameters ---------- ts : Ts or TsGroup The timestamps to shift. If TsGroup, shifts all Ts in the group independently. min_shift : float, optional minimum shift (default: 0 ) max_shift : float, optional maximum shift, (default: length of time support) Returns ------- Ts or TsGroup The randomly shifted timestamps """ strategies = { nap.time_series.Ts: _shift_ts, nap.ts_group.TsGroup: _shift_tsgroup, } # checks input type if type(ts) not in strategies.keys(): raise TypeError("Invalid input type, should be Ts or TsGroup") strategy = strategies[type(ts)] return strategy(ts, min_shift, max_shift)
# Random shuffle intervals between timestamps
[docs] def shuffle_ts_intervals(ts, min_shift=0.0, max_shift=None): """ Randomizes the timestamps by shuffling the intervals between them. Parameters ---------- ts : Ts or TsGroup The timestamps to randomize. If TsGroup, randomizes all Ts in the group independently. Returns ------- Ts or TsGroup The randomized timestamps, with shuffled intervals """ strategies = { nap.time_series.Ts: _shuffle_intervals_ts, nap.ts_group.TsGroup: _shuffle_intervals_tsgroup, } # checks input type if type(ts) not in strategies.keys(): raise TypeError("Invalid input type, should be Ts or TsGroup") strategy = strategies[type(ts)] return strategy(ts)
# Random Jitter
[docs] def jitter_timestamps(ts, max_jitter=None, keep_tsupport=False): """ Jitters each time stamp independently of random amounts uniformly drawn between -max_jitter and max_jitter. Parameters ---------- ts : Ts or TsGroup The timestamps to jitter. If TsGroup, jitter is applied to each element of the group. max_jitter : float maximum jitter keep_tsupport: bool, optional If True, keep time support of the input. The number of timestamps will not be conserved. If False, the time support is inferred from the jittered timestamps. The number of tmestamps is conserved. (default: False) Returns ------- Ts or TsGroup The jittered timestamps """ strategies = { nap.time_series.Ts: _jitter_ts, nap.ts_group.TsGroup: _jitter_tsgroup, } # checks input type if type(ts) not in strategies.keys(): raise TypeError("Invalid input type, should be Ts or TsGroup") if max_jitter is None: raise TypeError("missing required argument: max_jitter ") strategy = strategies[type(ts)] return strategy(ts, max_jitter, keep_tsupport)
# Random resample
[docs] def resample_timestamps(ts): """ Resamples the timestamps in the time support, with uniform distribution. Parameters ---------- ts : Ts or TsGroup The timestamps to resample. If TsGroup, each Ts object in the group is independently resampled, in the time support of the whole group. Returns ------- Ts or TsGroup The resampled timestamps """ strategies = { nap.time_series.Ts: _resample_ts, nap.ts_group.TsGroup: _resample_tsgroup, } # checks input type if type(ts) not in strategies.keys(): raise TypeError("Invalid input type, should be Ts or TsGroup") strategy = strategies[type(ts)] return strategy(ts)
# Helper functions def _shift_ts(ts, min_shift=0, max_shift=None): """ Shifts all the time stamps of a random amount between min_shift and max_shift, wrapping the end of the time support to the beginning. Parameters ---------- ts : Ts The timestamps to shift. min_shift : float, optional minimum shift (default: 0 ) max_shift : float, optional maximum shift, (default: length of time support) Returns ------- Ts The randomly shifted timestamps """ if max_shift is None: max_shift = ts.end_time() - ts.start_time() shift = np.random.uniform(min_shift, max_shift) shifted_timestamps = (ts.times() + shift) % ts.end_time() + ts.start_time() shifted_ts = nap.Ts(t=np.sort(shifted_timestamps), time_support=ts.time_support) return shifted_ts def _shift_tsgroup(tsgroup, min_shift=0, max_shift=None): """ Shifts each Ts in the Ts group independently. Parameters ---------- tsgroup : TsGroup The collection of Ts to shift. min_shift : float, optional minimum shift (default: 0 ) max_shift : float, optional maximum shift, (default: length of time support) Returns ------- TsGroup The TSGroup with randomly shifted timestamps """ start_time = tsgroup.time_support.start[0] end_time = tsgroup.time_support.end[0] if max_shift is None: max_shift = end_time - start_time shifted_tsgroup = {} for k in tsgroup.keys(): shift = np.random.uniform(min_shift, max_shift) shifted_timestamps = (tsgroup[k].times() + shift) % end_time + start_time shifted_tsgroup[k] = nap.Ts(t=np.sort(shifted_timestamps)) return nap.TsGroup(shifted_tsgroup, time_support=tsgroup.time_support) def _jitter_ts(ts, max_jitter=None, keep_tsupport=False): """ Parameters ---------- ts : Ts The timestamps to jitter. max_jitter : float maximum jitter keep_tsupport: bool, optional If True, keep time support of the input. The number of timestamps will not be conserved. If False, the time support is inferred from the jittered timestamps. The number of tmestamps is conserved. (default: False) Returns ------- Ts The jittered timestamps """ jittered_timestamps = ts.times() + np.random.uniform( -max_jitter, max_jitter, len(ts) ) if keep_tsupport: jittered_ts = nap.Ts( t=np.sort(jittered_timestamps), time_support=ts.time_support ) else: jittered_ts = nap.Ts(t=np.sort(jittered_timestamps)) return jittered_ts def _jitter_tsgroup(tsgroup, max_jitter=None, keep_tsupport=False): """ Jitters each time stamp independently, for each element in the TsGroup of random amounts uniformly drawn between -max_jitter and max_jitter. Parameters ---------- tsgroup : TsGroup The timestamps to jitter, the jitter is applied to each element of the group. max_jitter : float maximum jitter keep_tsupport: bool, optional If True, keep time support of the input. The number of timestamps will not be conserved. If False, the time support is inferred from the jittered timestamps. The number of tmestamps is conserved. (default: False) Returns ------- TsGroup The jittered timestamps """ jittered_tsgroup = {} for k in tsgroup.keys(): jittered_timestamps = tsgroup[k].times() + np.random.uniform( -max_jitter, max_jitter, len(tsgroup[k]) ) jittered_tsgroup[k] = nap.Ts(t=np.sort(jittered_timestamps)) if keep_tsupport: jittered_tsgroup = nap.TsGroup( jittered_tsgroup, time_support=tsgroup.time_support ) else: jittered_tsgroup = nap.TsGroup(jittered_tsgroup) return jittered_tsgroup def _resample_ts(ts): """ Resamples the timestamps in the time support, with uniform distribution. Parameters ---------- ts : Ts The timestamps to resample. Returns ------- Ts The resampled timestamps """ resampled_timestamps = np.random.uniform(ts.start_time(), ts.end_time(), len(ts)) resampled_ts = nap.Ts(t=np.sort(resampled_timestamps), time_support=ts.time_support) return resampled_ts def _resample_tsgroup(tsgroup): """ Resamples the each timestamp series in the group, with uniform distribution and on the time support of the whole group. Parameters ---------- tsgroup : TsGroup The TsGroup to resample, each Ts object in the group is independently resampled, in the time support of the whole group. Returns ------- TsGroup The resampled TsGroup """ start_time = tsgroup.time_support.start[0] end_time = tsgroup.time_support.end[0] resampled_tsgroup = {} for k in tsgroup.keys(): resampled_timestamps = np.random.uniform(start_time, end_time, len(tsgroup[k])) resampled_tsgroup[k] = nap.Ts(t=np.sort(resampled_timestamps)) return nap.TsGroup(resampled_tsgroup, time_support=tsgroup.time_support) def _shuffle_intervals_ts(ts): """ Randomizes the timestamps by shuffling the intervals between them. Parameters ---------- ts : Ts The timestamps to randomize. Returns ------- Ts The timestamps with shuffled intervals """ intervals = np.diff(ts.times()) shuffled_intervals = np.random.permutation(intervals) start_time = ts.times()[0] randomized_timestamps = np.hstack( [start_time, start_time + np.cumsum(shuffled_intervals)] ) randomized_ts = nap.Ts(t=randomized_timestamps) return randomized_ts def _shuffle_intervals_tsgroup(tsgroup): """ Randomizes the timestamps by shuffling the intervals between them. Each Ts in the group is randomized independently Parameters ---------- tsgroup : TsGroup The TsGroup to randomize. Returns ------- tsGroup The TsGroup with shuffled intervals. """ randomized_tsgroup = {k: _shuffle_intervals_ts(tsgroup[k]) for k in tsgroup.keys()} return nap.TsGroup(randomized_tsgroup)