我有一组x_i, y_i
表示非双射映射的点(没有一对一的对应关系。请参见所附图片:
(不要在第二行上注意。它只是显示中心质量)。我正在尝试在其上找到第一个峰(如您所见,它发现不正确)。代码如下。在这里,我通过Ox轴对点进行排序,然后使用find_peaks
函数:
# sort points by X axis
aa = zip(x,y)
bb = sorted(aa, key=lambda x: (x[0], x[1]))
x,y = zip(*bb)
x = np.array(x)
y = np.array(y)
# find all peaks
peaks, props = find_peaks(y, prominence=0.01, height=0.4)
print('rmax candidates=', y[peaks])
rmax = y[peaks[0]] # first peak is not correct
我注意到这里的排序处理不正确。如果仅绘制y
数组,则会看到图片:。我们在这里看到“齿轮非常锋利的齿轮”。
Thus, how to sort points (if I can set a starting point) in the closest way. For a human being draw a line through the graph is an easy task, but how to develop an algorithm for a computer? I know that a similar algorithm is already used in Online Digitizer. Where point coordinates from graphs can be easily extracted.
Maybe you have better algorithm for finding the first peak? If you have any questions, please, ask me.
The data can be found here:
The following idea can be given:
Read the file and put data into a 2D NumPy array.
arr = []
with open(str(Path('example.csv'))) as csv_file:
reader = csv.reader(csv_file, delimiter=',')
for row in reader:
arr.append([float(row[0]),float(row[1])])
arr = np.array(arr)
Since the data is unordered then when we connect points subsequently, we observe an ugly graph.
fig0 = go.Figure(go.Scatter(x=arr[:,0],y=arr[:,1], mode='lines'))
fig0.show()
To get an appropriate picture we need to sort points from some starting point in such a way that only the nearest points are connected
arx, x0, xmin, xmax = sort_by_nearest(arr)
x = arx[:,0]
y = arx[:,1]
排序后的数据y
看起来像:非双射行为消失了,我们可以y
使用find_peaks
函数轻松找到仅数据的第一个峰。prominence
是从一个山峰到下一个山峰的最小下降和上升高度。因此,小的噪声峰值将被丢弃。height
负责仅在以下区域搜索峰的参数y>height
peaks, props = find_peaks(y, prominence=0.01, height=0.4)
这里有几个候选人
print('rmax candidates=', y[peaks])
当然,我们拿第一个
rmax = y[peaks[0]]
x_rmax = x[peaks[0]] - x0
fig0 = go.Figure(go.Scatter(y=arx[:,1], mode='lines'))
fig0.show()
fig0 = go.Figure(go.Scatter(x=arx[:,0]-x0, y=arx[:,1], name='my_line', mode='lines'))
fig0.add_trace(go.Scatter(x=[x_rmax,x_rmax], y=[0,0.5], name='peak coord', mode='lines', line=dict(color='black', width=2, dash='dot')))
fig0.show()
让我们集中讨论按邻居对数据进行排序的算法。
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import csv
from scipy.signal import find_peaks
import scipy.spatial.distance as ds
from pathlib import Path
搜索最接近点的功能很棘手,我们需要以某种方式标记已经观察到的点,以避免无限循环。我们只是通过大修改数组副本的点坐标来做到这一点arr_full
def closest_point(arr_full, xi, yi, inds):
N = arr_full.shape[0]
arr_full[inds] = 1e+30
dist = (arr_full[:, 0] - xi)**2 + (arr_full[:, 1] - yi)**2
i_min = dist.argmin()
#returns an index of the nearest point and its coordinate
return i_min, arr_full[i_min][0], arr_full[i_min][1]
def sort_by_nearest(arr):
N = arr.shape[0]
nearest_point = [None]*N
#find initial point
xmin = min(arr[:,0])
xmax = max(arr[:,0])
# we copy the original array
arr_cut = np.copy(arr)
# the area in which we are 100% sure in absence of the starting point we flag by big value
arr_cut[arr[:,0] > 0.5*(xmin + xmax)] = 10e+30
iymin = arr_cut[:,1].argmin()
# the staring points are
x0, y0 = arr[iymin, 0], arr[iymin, 1]
# we initialize the sorted value nearest_point
nearest_point[0] = [arr[iymin,0],arr[iymin,1]]
print('Starting point:', x0, y0)
# we put in it the indices of visited points
observed = [iymin]
i_min = iymin
for i in range(1,N):
xi, yi = arr[i_min]
i_min, xip, yip = closest_point(arr, xi, yi, i_min)
nearest_point[i] = [xip, yip]
observed.append(i_min)
nearest_point = np.array(nearest_point)
return np.array(nearest_point), x0, xmin, xmax
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句