def extract_events_fit_all(ev, threshold, pos_step=2.0, amp_step=500.0): """ Последовательное выделение событий из блока Все события фитируются одновременно. @ev - массив события @threshold - порог @pos_step - максимальное отклонение по положению при фитировании @amp_step - максимальное положительное отклонение по амплитуде при фитировании. Нижняя граница всегда равна 0. @return параметры событий в формате [amp1, pos1, amp2, pos2, ...] """ points = get_peaks(ev, threshold) values = np.zeros(len(points) * 2) values[0::2] = ev[points] values[1::2] = points upper_bounds = values.copy() upper_bounds[1::2] = upper_bounds[1::2] + pos_step upper_bounds[0::2] = upper_bounds[0::2] + amp_step lower_bounds = values.copy() lower_bounds[1::2] = lower_bounds[1::2] - pos_step lower_bounds[0::2] = 0 full_func = lambda x, *values: gen_multiple(x, *values) popt, pcov = curve_fit(full_func, np.arange(len(ev)), ev, p0=list(values)) return popt
def extract_amps_approx(data, start_time, threshold, sample_freq): """ Последовательное выделение событий из блока с вычитанием предыдущих событий. Алгоритм имеет меньшую скорость работы по сравнению с extract_simple_amps, однако учитывет форму сигнала. Алгоритм: 1. Выделение локальных максимумов в кадре выше порога. 2. Последовательная обработка пиков: 1. Сохранение амплитуды и положения текущего пика. 2. Вычитание из данных формы сигнала, соответсвующей выделенным амплитуде и положению текущего события. 3. Переход к следующему событию. """ data = data.copy().astype(np.float32) peaks = get_peaks(data, threshold) params = np.zeros(len(peaks) * 2, np.float32) params[1::2] = ((peaks / sample_freq) * 1e+9) + start_time x = np.linspace(0, data.size / sample_freq, data.size) for i in range(len(peaks)): peak = peaks[i] amp = data[peak] params[i * 2] = amp data -= gen_multiple(x, amp, peak / sample_freq) singles = np.ones(peaks.shape, np.bool) return params, singles
def extract_events_fit(ev, threshold): """ Последовательное выделение событий из блока В блоке последовательно фитируются событие. Функция следующего события складывается с фунциями уже определенных ранее событий. Данный метод работает потенциально быстрее и стабильнее по сравнению с одновременным фитированием всех событий в блоке, выдает большую ошибку при выделении близко наложенных событий (событие накладывается на хвост предыдущего события). @ev - массив события @threshold - порог @return параметры событий в формате [amp1, pos1, amp2, pos2, ...] """ points = get_peaks(ev, threshold) values = np.array([], np.float32) for i, point in enumerate(points): y0, x0 = calc_center(ev, point) full_func = lambda x, a, p: gen_multiple(x, a, p, *values) popt, pcov = curve_fit(full_func, np.arange(len(ev)), ev, p0=[y0, x0]) values = np.hstack([values, popt]) return values
def extract_amps_approx3(data, start_time, threshold, sample_freq): """ Последовательное выделение событий из блока с вычитанием предыдущих событий. """ data = data.copy().astype(np.float64) x = np.linspace(0, data.size / sample_freq, data.size) params = [] while True: peaks = get_peaks(data, threshold) if not len(peaks): break peak = peaks[0] params.append(data[peak]) params.append(((peak / sample_freq) * 1e+9) + start_time) data -= gen_signal(x, data[peak], peak / sample_freq) params = np.array(params) singles = np.ones((params.shape[0] // 2), np.bool) return params, singles
def extract_fit_all(data, start_time, threshold, sample_freq, pos_step=2.0, amp_step=500.0): """ Выделение событий с помощью фитирования всех событий одновременно. Классификация наложений производится полносвязной нейронной сетью. Алгоритм требует высокой производительности, но дает наиболее точный результат. Алгоритм: 1. Выделение локальных максимумов в кадре выше порога. Локальные максимумы считаются предварительными пиками. 2. Классификация наложенных событий с помощью НС по предварительным пикам. 3. Одновременное фитирование всех пиков. В качестве начальных данных берутся предварительные пики и соответсвующие им амплитуды. Диапазоны фитирования задаются значениями pos_step и amp_step. """ if not extract_fit_all.model: if not 'load_model' in locals(): from keras.models import load_model extract_fit_all.model = load_model( path.join(path.dirname(__file__), "data/mlp_classifier.h5")) peaks = get_peaks(data, threshold) if not len(peaks): return np.array([]), np.array([]) prep_peaks = np.vstack([ data[peak - extract_fit_all.l_off:peak + extract_fit_all.r_off] for peak in peaks ]) singles = extract_fit_all.model.predict(prep_peaks/extract_fit_all.x_max)\ .argmax(axis=1).astype(np.bool) params = extract_events_fit_all(data, threshold, amp_step, pos_step) params[1::2] = ((params[1::2] / sample_freq) * 1e+9) + start_time return params, singles
def extract_amps_approx2(data, start_time, threshold, sample_freq, classify=False, frame_l=15, frame_r=25): """ Последовательное выделение событий из блока с вычитанием предыдущих событий. Ускоренный вариант extract_amps_approx. Вместо вычета события из всего кадра, событие вычитается только из пиков. Примерно на 30% медленее extract_simple_amps. @todo: Разобраться с сохранением времени в наносекундах """ peaks = get_peaks(data, threshold) if classify: if not extract_amps_approx2.bst: if not 'load_model' in locals(): global xgb xgb = __import__('xgboost') extract_amps_approx2.bst = xgb.Booster() model_path = path.join(path.dirname(__file__), 'data/xgb.dat') extract_amps_approx2.bst.load_model(model_path) frames = extract_frames(data.copy(), peaks, frame_l, frame_r) preds = extract_amps_approx2.bst.predict(xgb.DMatrix(frames)) singles = preds > 0.97 else: singles = np.ones(peaks.shape, np.bool) params = np.zeros(len(peaks) * 2, np.float32) params[0::2] = data[peaks] params[1::2] = ((peaks / sample_freq) * 1e+9) + start_time for i, peak in enumerate(peaks[:-1]): params[(i + 1) * 2::2] -= gen_signal(peaks[i + 1:], params[i * 2], peak) return params, singles
def extract_simple_amps(data, start_time, threshold, sample_freq): """ Выделение событий поиском локальных максимумов выше порога. Алгоритм является наиболее быстрым, однако он не учитывает форму сигнала, что приводит к систематической ошибке выделения амлитуд близких событий (событие попадает на хвост другого события). """ peaks = get_peaks(data, threshold) coeff = np.float128(1e+9 / sample_freq) params = np.zeros(len(peaks) * 2, np.float128) params[0::2] = data[peaks] params[1::2] = (np.float128(peaks) * coeff) + start_time singles = np.ones(peaks.shape, np.bool) return params, singles