def detect_changepoints(points, min_time, data_processor=acc_difference): """ Detects changepoints on points that have at least a specific duration Args: points (:obj:`Point`) min_time (float): Min time that a sub-segmented, bounded by two changepoints, must have data_processor (function): Function to extract data to feed to the changepoint algorithm. Defaults to `speed_difference` Returns: :obj:`list` of int: Indexes of changepoints """ data = data_processor(points) changepoints = pelt(normal_mean(data, np.std(data)), len(data)) changepoints.append(len(points) - 1) result = [] for start, end in pairwise(changepoints): time_diff = points[end].time_difference(points[start]) if time_diff > min_time: result.append(start) # adds the first point result.append(0) # adds the last changepoint detected result.append(len(points) - 1) return sorted(list(set(result)))
def test_pelt_normal_mean_small(self): """ Test normal changing mean, with smaller dataset """ var = 0.1 data = [ 0.16853651, 0.0261112, -0.0655322, 0.11575204, 0.11388594, 10.001775, 9.92765733, 10.01303474, 9.97938986, 10.05994745 ] result = pelt(normal_mean(data, var), len(data)) self.assertEqual(result, [0, 5])
def test_pelt_normal_mean_big(self): """ Test normal changing mean, with bigger dataset """ size = 100 mean_a = 0.0 mean_b = 10.0 var = 0.1 np.random.seed(19348) data_a = np.random.normal(mean_a, var, size) data_b = np.random.normal(mean_b, var, size) data = np.append(data_a, data_b) result = pelt(normal_mean(data, var), len(data)) self.assertEqual(result, [0, size])
sp_der = sp_dset.derivative(n=1) dset_der = sp_der(frames) #--------------------------------------------------------------------------------------- #Q, P, Pcp = offcd.offline_changepoint_detection(dset_der, partial(offcd.const_prior, # l=(len(dset_der)+1)), offcd.gaussian_obs_log_likelihood, truncate=-50) #--------------------------------------------------------------------------------------- dset_var = np.var(dset_der) #Q, P, Pcp = offcd.offline_changepoint_detection(dset_var, \ # partial(offcd.const_prior, l=(len(dset_var)+1)), \ # offcd.gaussian_obs_log_likelihood, truncate=-40) changepts = pelt( normal_mean(dset_der, var_user), len(dset_der)) #var_scale*dset_var #var_scale_testdata*len(dset_der) #changepts = pelt(normal_meanvar(dset_der),len(dset_der)) N = len(dset_der) - 1 if 0 not in changepts: changepts.insert(0, 0) #if len(dset_der) not in changepts: # changepts.append(len(dset_der)) if N not in changepts: changepts.append(N) #print(changepts) #---------------------------------------------------------------------------------------
def pelt_(data): return pelt(normal_mean(data, np.std(data)), len(data))
def bout_analysis(dset, frames, var_user=analysisParams['var_user'], var_user_flag=False, mad_thresh=analysisParams['mad_thresh']): wlevel = analysisParams['wlevel'] wtype = analysisParams['wtype'] medfilt_window = analysisParams['medfilt_window'] #var_scale = .5 #var_scale_testdata = 2*(1.3e-4) #mad_thresh = analysisParams['mad_thresh'] #var_user = analysisParams['var_user'] min_bout_duration = analysisParams['min_bout_duration'] min_bout_volume = analysisParams['min_bout_volume'] #--------------------------------------------------------------------------------------- dset_denoised = wavelet_denoise(dset, wtype, wlevel) dset_denoised_med = signal.medfilt(dset_denoised, medfilt_window) sp_dset = interpolate.InterpolatedUnivariateSpline( frames, np.squeeze(dset_denoised_med)) sp_der = sp_dset.derivative(n=1) dset_der = sp_der(frames) if var_user_flag == False: iq_range = np.percentile(dset_der, 75) - np.percentile(dset_der, 25) var_user = np.power(iq_range, 2.0) / 2.0 #--------------------------------------------------------------------------------------- #dset_var = np.var(dset_der) changepts = pelt( normal_mean(dset_der, var_user), len(dset_der)) #var_scale*dset_var #var_scale_testdata*len(dset_der) #changepts = pelt(normal_meanvar(dset_der),len(dset_der)) N = len(dset_der) - 1 if 0 not in changepts: changepts.insert(0, 0) #if len(dset_der) not in changepts: # changepts.append(len(dset_der)) if N not in changepts: changepts.append(N) #print(changepts) #--------------------------------------------------------------------------------------- piecewise_fits = np.empty(len(changepts) - 1) piecewise_fit_dist = np.empty_like(dset_der) for i in range(0, len(changepts) - 1): ipt1 = changepts[i] ipt2 = changepts[i + 1] + 1 fit_temp = np.median(dset_der[ipt1:ipt2]) piecewise_fits[i] = fit_temp piecewise_fit_dist[ipt1:ipt2] = fit_temp * np.ones_like( dset_der[ipt1:ipt2]) #mean_pw_slope = np.mean(piecewise_fit_dist) #std_pw_slope = np.std(piecewise_fit_dist) mad_slope = np.median(np.abs(np.median(dset_der) - dset_der)) piecewise_fits_dev = (piecewise_fits - np.median(dset_der)) / mad_slope bout_ind = (piecewise_fits_dev < mad_thresh ) #~z score of 1 #(mean_pw_slope - std_pw_slope) bout_ind = bout_ind.astype(int) bout_ind_diff = np.diff(bout_ind) #plt.figure() #plt.plot(bout_ind) bouts_start_ind = np.where(bout_ind_diff == 1)[0] + 1 bouts_end_ind = np.where(bout_ind_diff == -1)[0] + 1 #print(bouts_start_ind) #print(bouts_end_ind) if len(bouts_start_ind) != len(bouts_end_ind): minLength = np.min([len(bouts_start_ind), len(bouts_end_ind)]) bouts_start_ind = bouts_start_ind[0:minLength] bouts_end_ind = bouts_end_ind[0:minLength] #print(bouts_start_ind) #print(bouts_end_ind) changepts_array = np.asarray(changepts) bouts_start = changepts_array[bouts_start_ind] bouts_end = changepts_array[bouts_end_ind] bouts = np.vstack((bouts_start, bouts_end)) volumes = dset_denoised_med[bouts_start] - dset_denoised_med[bouts_end] bout_durations = bouts_end - bouts_start good_ind = (bout_durations > min_bout_duration) & (volumes > min_bout_volume) bouts = bouts[:, good_ind] volumes = volumes[good_ind] return (dset_denoised_med, bouts, volumes)