Premise
I have a 3D dataset of a system responding to different frequencies https://pastebin.com/9MyQ6S74
(x: imposed frequency (f1) y: response frequency z: response amplitude)
I know that the system will respond to a frequency that always follows a standard intermodulation product response:
m f1 + n f2, where m,n integer (positive or negative) and f1 the stimulus and f2 a fixed number (here at 600 Hz).
data = Import["SE_example.txt", "TSV"];
ListDensityPlot[data, PlotRange -> Full, ImageSize -> 400,
FrameLabel -> {"Stimulus frequency [Hz]", "Response [Hz]"}]
Question
I am interested in finding a way to automatically detect these lines and be able to at least extract slope and offset.
What I have tried so far
The manual method
The most labour intensive method is to simply right click onto the plot and get the coordinate positions of two points along a line, and from there extract the coefficient terms. This is fair enough when the system is simple, but when you have 50+ 'lines' and multiple datasets, it can be a drag.
Using ImageLines
Another thing I tried was to raster the plot into an image and then use ImageLines to give me an idea as to where to look.
(* I unitise the data to make it a bit more clear for the image *)
data[[;; , 3]] = data[[;; , 3]] /. x_ /; x < 0.02 -> 0;
data[[;; , 3]] = data[[;; , 3]] /. x_ /; x > 0 -> 1;
(* then I raster the output of the ListDensityPlot without any frame to not confuse ImageLines *)
rasterImage =
Rasterize[
ListDensityPlot[data, PlotRange -> Full, ImageSize -> 400,
Frame -> False, ImagePadding -> None, FrameTicks -> None,
PlotRangePadding -> None]]
Manipulate[
lines = ImageLines[rasterImage, t, d,
Method -> {"Segmented" -> True}, MaxFeatures -> 100];
HighlightImage[rasterImage, lines], {t, 0, 1}, {{d, 0.05}, 0, 1},
Paneled -> False]
Using Manipulate, I played around with different thresholds to see what could work. The RANSAC and Hough methods are not particularly good as the data are not strictly speaking 'continuous' but there are some small gaps for a given line. As you can see below, it does identify the major points when the Method is set to Method->{"Segmented"->True} but because of the segmentation it is generating lines in all sorts of directions which is not helpful.
GradientFilter?
Having a look at this thread, I can appreciate that GradientFilter could be a useful approach, but I am not certain how I could use it in this 3D context.
A potential start could be to reduce the dimensionality based on a threshold:
ListPlot[rdata = Select[data, #[[3]] > 0.02 &][[;; , {1, 2}]],
PlotStyle -> AbsoluteThickness[2]]
Any suggestions would be very welcome.
Thank you in advance!




