def _seg(self, n_bkps=None, pen=None, epsilon=None): """Sequential peak search. The stopping rule depends on the parameter passed to the function. Args: n_bkps (int): number of breakpoints to find before stopping. penalty (float): penalty value (>0) epsilon (float): reconstruction budget (>0) Returns: list: breakpoint index list """ # initialization bkps = [self.n_samples] stop = False error = self.cost.sum_of_costs(bkps) # peak search peak_inds_shifted, = argrelmax(self.score, order=max(self.width, self.min_size) // (2 * self.jump), mode="wrap") if peak_inds_shifted.size == 0: # no peaks if the score is constant return bkps gains = np.take(self.score, peak_inds_shifted) peak_inds_arr = np.take(self.inds, peak_inds_shifted) # sort according to score value _, peak_inds = unzip(sorted(zip(gains, peak_inds_arr))) peak_inds = list(peak_inds) while not stop: stop = True # _, bkp = max((v, k) for k, v in enumerate(self.score, start=1) # if not any(abs(k - b) < self.width // 2 for b in bkps[:-1])) try: # index with maximum score bkp = peak_inds.pop() except IndexError: # peak_inds is empty break if n_bkps is not None: if len(bkps) - 1 < n_bkps: stop = False elif pen is not None: gain = error - self.cost.sum_of_costs(sorted([bkp] + bkps)) if gain > pen: stop = False elif epsilon is not None: if error > epsilon: stop = False if not stop: bkps.append(bkp) bkps.sort() error = self.cost.sum_of_costs(bkps) return bkps
def _seg(self, n_bkps=None, pen=None, epsilon=None): """Sequential peak search. The stopping rule depends on the parameter passed to the function. Args: n_bkps (int): number of breakpoints to find before stopping. penalty (float): penalty value (>0) epsilon (float): reconstruction budget (>0) Returns: list: breakpoint index list """ # initialization bkps = [self.n_samples] stop = False error = self.cost.sum_of_costs(bkps) # peak search # forcing order to be above one in case jump is too large (issue #16) order = max(max(self.width, 2 * self.min_size) // (2 * self.jump), 1) peak_inds_shifted = argrelmax(self.score, order=order, mode="wrap")[0] if peak_inds_shifted.size == 0: # no peaks if the score is constant return bkps gains = np.take(self.score, peak_inds_shifted) peak_inds_arr = np.take(self.inds, peak_inds_shifted) # sort according to score value _, peak_inds = unzip(sorted(zip(gains, peak_inds_arr))) peak_inds = list(peak_inds) while not stop: stop = True # _, bkp = max((v, k) for k, v in enumerate(self.score, start=1) # if not any(abs(k - b) < self.width // 2 for b in bkps[:-1])) try: # index with maximum score bkp = peak_inds.pop() except IndexError: # peak_inds is empty break if n_bkps is not None: if len(bkps) - 1 < n_bkps: stop = False elif pen is not None: gain = error - self.cost.sum_of_costs(sorted([bkp] + bkps)) if gain > pen: stop = False elif epsilon is not None: if error > epsilon: stop = False if not stop: bkps.append(bkp) bkps.sort() error = self.cost.sum_of_costs(bkps) # remove shifts if they last too long start_index = 0 end_index = 1 to_delete = [] if self.max_samples is not None and len(bkps) > 1: for i in range(math.floor(len(bkps) / 2)): if (bkps[end_index] - bkps[start_index]) > self.max_samples: to_delete.append(start_index) to_delete.append(end_index) start_index += 2 end_index += 2 bkps = list(np.delete(bkps, to_delete)) # remove changepoint if it starts but never ends if self.remove_single: if (len(bkps) % 2) != 0: del bkps[-1] return bkps