I would like to seperate the fringes (the red curved lines) that I have calculated with scipy findpeaks how can I achive it. I would like to seperate them and store in the text file.
import numpy as np
from scipy.signal import find_peaks
import matplotlib.pyplot as plt
X = np.load('X.npy')
Y = np.load('Y.npy')
P_new = np.load('P_new.npy')
# Example data: Replace with your actual data
T = np.real(P_new) # Simulating a 2D matrix
# Plot the original image
plt.figure()
plt.imshow(T, cmap='jet', aspect='auto')
plt.colorbar()
plt.title('Original Image')
plt.show()
# Peak detection parameters
min_peak_dist = 3 # Minimum distance between peaks
min_peak_h = 3e-5 # Minimum peak height
x_coords = []
y_coords = []
# Process all rows from top to bottom
for k in range(T.shape[0]):
tex = T[k, :]
peaks, _ = find_peaks(tex, distance=min_peak_dist, height=min_peak_h)
if peaks.size > 0:
x_coords.extend(X[k, peaks])
y_coords.extend(Y[k, peaks])
# Plot detected peaks
plt.figure()
plt.scatter(x_coords, y_coords, color='r', s=2) # 's' controls marker size
plt.xlabel('X Coordinate')
plt.ylabel('Y Coordinate')
plt.title('Detected Fringes in Real-World Coordinates')
plt.colorbar()
plt.show()
data for plotting is here
Want I want see is just seperate fringes like here:
previously I could do it with cv2 method contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) but this is from finding the edges which is not very rigorous for my case as with finding peaks of the actual data.
Can someone help with this? Thanks
I would like to seperate the fringes (the red curved lines) that I have calculated with scipy findpeaks how can I achive it. I would like to seperate them and store in the text file.
import numpy as np
from scipy.signal import find_peaks
import matplotlib.pyplot as plt
X = np.load('X.npy')
Y = np.load('Y.npy')
P_new = np.load('P_new.npy')
# Example data: Replace with your actual data
T = np.real(P_new) # Simulating a 2D matrix
# Plot the original image
plt.figure()
plt.imshow(T, cmap='jet', aspect='auto')
plt.colorbar()
plt.title('Original Image')
plt.show()
# Peak detection parameters
min_peak_dist = 3 # Minimum distance between peaks
min_peak_h = 3e-5 # Minimum peak height
x_coords = []
y_coords = []
# Process all rows from top to bottom
for k in range(T.shape[0]):
tex = T[k, :]
peaks, _ = find_peaks(tex, distance=min_peak_dist, height=min_peak_h)
if peaks.size > 0:
x_coords.extend(X[k, peaks])
y_coords.extend(Y[k, peaks])
# Plot detected peaks
plt.figure()
plt.scatter(x_coords, y_coords, color='r', s=2) # 's' controls marker size
plt.xlabel('X Coordinate')
plt.ylabel('Y Coordinate')
plt.title('Detected Fringes in Real-World Coordinates')
plt.colorbar()
plt.show()
data for plotting is here
Want I want see is just seperate fringes like here:
previously I could do it with cv2 method contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) but this is from finding the edges which is not very rigorous for my case as with finding peaks of the actual data.
Can someone help with this? Thanks
Share Improve this question asked 2 days ago wosker4yanwosker4yan 3131 gold badge4 silver badges14 bronze badges 5 |1 Answer
Reset to default 2I had reasonable success using HDBSCAN
.
I first ran find_peaks
to find peaks along y (rather than along x) - these are the black lines. I then clipped the image to within the blue square, and clustered the points using HDBSCAN. The final clusterings are coloured.
To plot a particular cluster, you could use:
view_cluster = 20
plt.figure(figsize=(3, 5))
plt.scatter(*clustered[view_cluster].T, marker='.', s=1)
plt.xlabel('x')
plt.ylabel('y')
plt.title(f'Fringe {view_cluster}')
plt.grid(linestyle=':')
Solution
Load data and preprocess:
import numpy as np
from scipy.signal import find_peaks
import matplotlib.pyplot as plt
from matplotlib.patheffects import withTickedStroke
#
# Example data: Replace with your actual data
#
X_orig = np.load('X.npy')
Y_orig = np.load('Y.npy')
P_new = np.load('P_new.npy')
n_rows, n_cols = P_new.shape
T = np.real(P_new) # Simulating a 2D matrix
#Resample X and Y to match resolution of P_new
# NB. I use the min/max values for simplicity
x_axis = np.linspace(X_orig.min(), X_orig.max(), num=n_cols)
y_axis = np.linspace(Y_orig.min(), Y_orig.max(), num=n_rows)
X_grid, Y_grid = np.meshgrid(x_axis, y_axis)
# Peak detection parameters
min_peak_dist = 3 # Minimum distance between peaks
min_peak_h = 3e-5 # Minimum peak height
coords = []
# Process all cols (x axis)
for col_ix in range(n_cols):
peaks, _ = find_peaks(T[:, col_ix], distance=min_peak_dist, height=min_peak_h)
if not len(peaks):
continue
x_coord = x_axis[col_ix]
peaks_y = y_axis[peaks]
coords.extend([(x_coord, peak_y) for peak_y in peaks_y])
coords = np.array(coords)
x_coords, y_coords = coords.T
#
#Clip unwanted regions
#
ignore_left_of = 5
ignore_below = 25
# ignore_shorter_than = 10
coords_clipped = coords[(x_coords > ignore_left_of) & (y_coords > ignore_below)]
Cluster and visualise:
#
# HDBSCAN
#
from sklearn.cluster import HDBSCAN
coord_labels = HDBSCAN().fit_predict(coords_clipped)
clustered = [
coords_clipped[coord_labels==cluster_id]
for cluster_id in np.unique(coord_labels)
]
#
# Visualise
#
plt.figure()
#Original image
plt.matshow(
T, extent=[x_axis.min(), x_axis.max(), y_axis.min(), y_axis.max()],
cmap='Greys_r', origin='lower', vmax=5e-4, aspect='auto'
)
plt.gcf().set_size_inches(12, 6)
plt.colorbar(extend='both')
#Detected peaks
plt.scatter(x_coords, y_coords, color='black', marker='.', s=0.2, alpha=0.4)
# #Clip regions
plt.axvline(ignore_left_of, path_effects=[withTickedStroke(angle=135)])
plt.axhline(ignore_below, path_effects=[withTickedStroke(angle=-135)])
#Clusters
clustered = sorted(clustered, key=lambda members: members[:, 1].min())
for cluster_members in clustered:
plt.plot(*cluster_members[::30].T, alpha=0.2, zorder=0, lw=8)
#Formatting
plt.xlabel('x')
plt.ylabel('y')
plt.show()
networkx.from_numpy_array
. – Reinderien Commented 2 days agoIndexError: index 3100 is out of bounds for axis 0 with size 100
– Reinderien Commented 2 days ago