Mam zestaw punktów x_i, y_i, który reprezentuje mapowanie , a nie bijective (nie ma jednego do jednej korespondencji. Zobacz załączony obraz: Wpisz opis obrazu tutaj

(Nie zwracaj uwagi na drugą linię. Wystarczy pokazać masę środkową). Próbuję znaleźć na nim pierwszy szczyt (jak widać, nie jest to poprawnie). Kod podano poniżej. Tutaj jestem sortowanie punktami OX osi, a następnie za pomocą funkcji 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

Zauważyłem, że tutaj sortowanie przetworzone nieprawidłowo . Jeśli spłoduję tylko y array, a potem widzę zdjęcie: Wpisz opis obrazu tutaj. Gdzie widzimy "narzędzie z bardzo ostrymi zębami".

Tak więc, jak sortować punkty (jeśli mogę ustawić punkt wyjścia) w najbliższy sposób. Dla człowieka rysuje linię przez wykres, jest łatwym zadaniem, ale jak opracować algorytm komputera? Wiem, że podobny algorytm jest już używany w Digitizer online. Gdzie koordynaty punktowe z wykresów można łatwo wyodrębnić.

Może masz lepszy algorytm do znalezienia pierwszego szczytu? Jeśli masz jakieś pytania, proszę, zapytaj mnie.

Dane można znaleźć Oto:

1
Eugene W. 18 październik 2020, 15:52

1 odpowiedź

Najlepsza odpowiedź

Można podać następujący pomysł:

Przeczytaj plik i umieść dane do tablicy 2D Numpy.

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)

Ponieważ dane są nieuporządkowane wtedy, gdy następnie połączamy punkty, obserwujemy brzydki wykres.

fig0 = go.Figure(go.Scatter(x=arr[:,0],y=arr[:,1], mode='lines'))
fig0.show()

enter image description here

Aby uzyskać odpowiedni obraz, musimy sortować punkty z pewnego punktu wyjścia w taki sposób, że tylko najbliższe punkty są połączone

arx, x0, xmin, xmax = sort_by_nearest(arr)
x = arx[:,0]
y = arx[:,1]

Po sortowaniu danych {X0}} wygląda: Wpisz opis obrazu tutaj A zachowanie bez bijective nie ma i możemy łatwo znaleźć pierwszy szczyt tylko dla danych {x1}} za pomocą {x2}} funkcja. prominence jest minimalną wysokość zejścia i wejścia z szczytu do następnego piku. Tak więc małe hałaśliwe szczyty zostaną odrzucone. height jest odpowiedzialny za parametr, w którym szczyty zostaną przeszukiwane tylko w regionach, w których y>height

peaks, props = find_peaks(y, prominence=0.01, height=0.4)

Tutaj mamy kilku kandydatów

print('rmax candidates=', y[peaks])

Oczywiście bierzemy pierwszy

rmax = y[peaks[0]]
x_rmax = x[peaks[0]] - x0

Narysujmy wynik: Wpisz opis obrazu tutaj

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()

Skupmy się na algorytmie do sortowania danych przez sąsiadów.

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

Funkcja wyszukiwania najbliższego punktu jest trudna, musimy w jakiś sposób, musimy w jakiś sposób obserwować, aby uniknąć nieskończonych cykli. Robimy to tylko poprzez modyfikację skoordy punktów według dużej liczby kopii tablicy 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
0
Eugene W. 19 październik 2020, 10:33