2013-07-29 33 views
5

Tôi đang phân tích dữ liệu từ các thử nghiệm kéo theo chu kỳ. Khi đầu vào được sử dụng lớn danh sách giá trị x và y. Để mô tả nếu vật liệu cứng hoặc mềm, tôi cần có độ dốc màu xanh của mỗi vòng chu kỳ.FInd tất cả các giao điểm của biểu đồ điểm dữ liệu xy có numpy?

tensile_test

slope

Lấy điểm thấp hơn của dốc là lễ hội trẻ em, nhưng một trong những thượng, đó là thách thức.

the_challenge

Tôi đã thực hiện phương pháp này cho đến nay, cắt ra các vòng với một vài điểm dưới mức tối đa địa phương của mỗi vòng lặp và làm cho đường màu đỏ từ hardnumbered đếm điểm. Việc tính toán đường đỏ được thực hiện bởi poly1d(polyfit(x1,x2,1))fsolve được sử dụng sau đó để có được điểm giao nhau. Tuy nhiên nó không hoạt động một cách chính xác, bởi vì sự phân bố các điểm không phải lúc nào cũng giống nhau.

Vấn đề là làm thế nào để xác định một cách chính xác khoảng hai (màu đỏ) giao nhau dòng. Trong hình trên là 3 thí nghiệm cùng với độ dốc trung bình. Tôi đã dành vài ngày cố gắng tìm 4 điểm gần nhất cho mỗi vòng lặp quyết định đây không phải là cách tiếp cận tốt nhất. Và cuối cùng, tôi đã kết thúc ở đây tại stackowerflow.

Đầu ra mong muốn là danh sách với tọa độ gần đúng của điểm giao nhau - nếu bạn muốn phát, here là dữ liệu cho đường cong (0, [[xvals], [khoảng]]). Theese có thể dễ dàng đọc với

import csv 
import sys 
csv. field_size_limit(sys.maxsize)  

csvfile = 'data.csv' 
tc_data = {} 
for key, val in csv.reader(open(csvfile, "r")): 
    tc_data[key] = val 
for key in tc_data: 
    tc = eval(tc_data[key]) 

x = tc[0] 
y = tc[1] 
+0

Không liên kết của bạn đang làm việc cho tôi. – gggg

+1

Tôi tự hỏi làm thế nào bạn đạt được hiệu ứng zoom-in với matplotlib –

Trả lời

6

Đây có thể là quá mức cần thiết chút, nhưng cách thích hợp để tìm giao điểm của bạn, một khi bạn đã chia tay đường cong của bạn vào khối, là để xem nếu bất kỳ phân đoạn từ đoạn đầu tiên giao cắt với bất kỳ phân đoạn từ đoạn thứ hai.

Tôi sẽ làm cho bản thân mình một số dữ liệu dễ dàng, một mảnh của một prolate cycloid, và đang đi tìm những nơi mà y phối hợp flips từ tăng để giảm tương tự như here:

a, b = 1, 2 
phi = np.linspace(3, 10, 100) 
x = a*phi - b*np.sin(phi) 
y = a - b*np.cos(phi) 
y_growth_flips = np.where(np.diff(np.diff(y) > 0))[0] + 1 

plt.plot(x, y, 'rx') 
plt.plot(x[y_growth_flips], y[y_growth_flips], 'bo') 
plt.axis([2, 12, -1.5, 3.5]) 
plt.show() 

enter image description here

Nếu bạn có hai đoạn, một đoạn đi từ điểm P0 đến P1 và một đoạn khác đi từ điểm Q0 đến Q1, bạn có thể tìm điểm giao nhau của chúng bằng cách giải phương trình vectơ P0 + s*(P1-P0) = Q0 + t*(Q1-Q0) và hai phân đoạn thực sự giao nhau nếu cả hai st đều ở trong [0, 1].Cố gắng này ra cho tất cả các phân đoạn:

x_down = x[y_growth_flips[0]:y_growth_flips[1]+1] 
y_down = y[y_growth_flips[0]:y_growth_flips[1]+1] 
x_up = x[y_growth_flips[1]:y_growth_flips[2]+1] 
y_up = y[y_growth_flips[1]:y_growth_flips[2]+1] 

def find_intersect(x_down, y_down, x_up, y_up): 
    for j in xrange(len(x_down)-1): 
     p0 = np.array([x_down[j], y_down[j]]) 
     p1 = np.array([x_down[j+1], y_down[j+1]]) 
     for k in xrange(len(x_up)-1): 
      q0 = np.array([x_up[k], y_up[k]]) 
      q1 = np.array([x_up[k+1], y_up[k+1]]) 
      params = np.linalg.solve(np.column_stack((p1-p0, q0-q1)), 
            q0-p0) 
      if np.all((params >= 0) & (params <= 1)): 
       return p0 + params[0]*(p1 - p0) 

>>> find_intersect(x_down, y_down, x_up, y_up) 
array([ 6.28302264, 1.63658676]) 

crossing_point = find_intersect(x_down, y_down, x_up, y_up) 
plt.plot(crossing_point[0], crossing_point[1], 'ro') 
plt.show() 

enter image description here

Trên hệ thống của tôi, điều này có thể xử lý khoảng 20 nút giao thông mỗi giây, mà không phải là siêu nhanh, nhưng có lẽ đủ để phân tích đồ thị tất cả bây giờ và sau đó. Bạn có thể spped số bằng những giải pháp của các hệ thống 2x2 tuyến tính vectorizing:

def find_intersect_vec(x_down, y_down, x_up, y_up): 
    p = np.column_stack((x_down, y_down)) 
    q = np.column_stack((x_up, y_up)) 
    p0, p1, q0, q1 = p[:-1], p[1:], q[:-1], q[1:] 
    rhs = q0 - p0[:, np.newaxis, :] 
    mat = np.empty((len(p0), len(q0), 2, 2)) 
    mat[..., 0] = (p1 - p0)[:, np.newaxis] 
    mat[..., 1] = q0 - q1 
    mat_inv = -mat.copy() 
    mat_inv[..., 0, 0] = mat[..., 1, 1] 
    mat_inv[..., 1, 1] = mat[..., 0, 0] 
    det = mat[..., 0, 0] * mat[..., 1, 1] - mat[..., 0, 1] * mat[..., 1, 0] 
    mat_inv /= det[..., np.newaxis, np.newaxis] 
    import numpy.core.umath_tests as ut 
    params = ut.matrix_multiply(mat_inv, rhs[..., np.newaxis]) 
    intersection = np.all((params >= 0) & (params <= 1), axis=(-1, -2)) 
    p0_s = params[intersection, 0, :] * mat[intersection, :, 0] 
    return p0_s + p0[np.where(intersection)[0]] 

Vâng, nó lộn xộn, nhưng nó hoạt động, và làm nhanh hơn lần để x100:

find_intersect(x_down, y_down, x_up, y_up) 
Out[67]: array([ 6.28302264, 1.63658676]) 

find_intersect_vec(x_down, y_down, x_up, y_up) 
Out[68]: array([[ 6.28302264, 1.63658676]]) 

%timeit find_intersect(x_down, y_down, x_up, y_up) 
10 loops, best of 3: 66.1 ms per loop 

%timeit find_intersect_vec(x_down, y_down, x_up, y_up) 
1000 loops, best of 3: 375 us per loop 
+0

Jaime, tôi nợ bạn thùng bia. Gửi cho tôi địa chỉ của bạn và tôi sẽ gửi nó ngay lập tức! – ptaeck

+0

Tôi nhận được TypeError: int được yêu cầu tại dòng 'intersection = np.all ((params> = 0) & (params <= 1), axis = (- 1, -2))' của 'find_intersect_vec' với prolate của bạn dữ liệu ví dụ cycloid. – ptaeck

+0

Bạn đang sử dụng phiên bản nào? Nhiều trục được giới thiệu trong 1.7, nếu bạn đang sử dụng phiên bản cũ hơn, bạn có thể phải lồng hai cuộc gọi đến 'np.all', tôi nghĩ' intersection = np.all (np.all ((params> = 0) & (params <= 1), trục = -1), trục = -1) 'nên làm tương tự trong 1,6. – Jaime