PDA

View Full Version : Overlapping plots



Thibaut
3rd January 2020, 10:53
Hi!

I have to make an application for eeg data visualization.

This post contain an example of what I want: https://forum.qt.io/topic/107467/plot-eeg-samples

As you can see, each graph share the x axis, and has its own "0" on the y axis. Each y axis are equally separated, and the graphs can overlap each other.

Right now, I'm able to display all the graph (they have transparent background) in a vertical layout, but I can't find a way to make them overlap.
I'm using QCustomPlot, with each plot containing only one graph. I tried putting all the graphs in only one plot and creating multiple y axis, but the problem is the same, with each plot one below the other...

Do you have any suggestion ? Maybe placing the widget by using coordinates instead of layout ? But it seems prone to errors as I have a variable number of graph...

d_stranz
3rd January 2020, 18:56
One way to do this is to add a y-offset value to each data point in the plots. So for the lowest plot, the y-offset is zero, for the second plot, the y-offset is 100, for the third plot it is 200, etc. You are not changing your raw data, just adding the offset to each of the y-values that you send to QCustomPlot. (0, 100, 200, etc. are just examples - I do not know the data ranges for EEG signals, so choose something appropriate).

ChrisW67
4th January 2020, 08:43
Just to clarify d_stranz's approach: it is a single QCustomPlot with many graphs on the same axes (which in your example are not marked with units). The data fed to each graph (after the first) is offset vertically to place it somewhere other than along the principal x axis line.

In your qt.io post you talk about updating the plot collection 100 times per second. You should look at QCPGraph::setAdaptiveSampling as one possible performance improvement.
Updating the entire plot every time a sample comes in is probably unnecessary: the user is unlikely to be hanging on every sample as it runs so an update every 10 or 20 samples would likely be adequate. You still have the raw data if it needs to be inspected in finer detail without the real time constraint.

Thibaut
7th January 2020, 08:45
Thank to you two!
Offsetting the data work fine to make the graph overlap in a single plot.
I'm only doing an offline visualization application, so there will be no real-time data reading (that was just an example from someone else).

I just hope it wouldn't be too slow to display everything when I use real data that contain a lot of points ^^

d_stranz
7th January 2020, 17:13
I just hope it wouldn't be too slow to display everything when I use real data that contain a lot of points ^^

It should not be too much of a problem. QCustomPlot is pretty good. If you do have performance problems, you can play some tricks with the data or derive a new line type for QCustomPlot.

I have some line plots that contain more than 1 million points. In a window that is only 1000 pixels wide, that means 1000 data points per pixel. Obviously, it is ridiculous to plot each point, so my line drawing keeps track of the current x-pixel value. As long as the x-pixel doesn't change, I find the minimum and maximum y-pixel values. When the x-pixel changes, I plot a vertical line at the original x-pixel value. (There is also a line from the last y-pixel value for the last x-pixel to the first y-pixel value for the next x-pixel. This ensures that as you zoom in, the points are connected by a continuous line). If your data are noisy, this gives a noisy-looking plot. If the data is not noisy, it looks good too. If you zoom in, the algorithm still works.

I optimize further by creating a QPainterPath instead of computing the lines for each redraw. So the redraw is simply repainting the path, not all 1 million points. Only if the zoom level or window size changes, the path has to be recomputed otherwise the QPainterPath is still good.