Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Display analog waveform with millions of samples

Hello,

i am trying to display a large waveform with up to 33 million samples in an analog waveform graph with Measurement Studio 8.0.1 for .Net. My first and very simple attempt was to plot the data with the PlotY() method of the WaveformPlot class. This worked but nevertheless suffered from the following downsides:

i) When displaying all samples or a large part of them, the drawing of the waveform is very slow. This is probably due to the fact that millions of samples are drawn. I tried with some success to overcome this problem by writing a custom plot method (using the BeforeDraw event) that uses only every hundredth or so data sample. But maybe there is a better solution to this problem?

ii) I copied the samples into an array of doubles for use with the PlotY() method. As our samples are only two bytes long but doubles are eight bytes long, this solution needs four times of memory. Furthermore, with 33 million data samples 264 million bytes are allocated, which may lead to memory swapping on some computers. Would it be more efficient to use the  AnalogWaveform<UInt16> class and the PlotWaveform() method?


Regards,
Jörg

0 Kudos
Message 1 of 7
(4,433 Views)
Please can you post a project that plots all your data (33 million samples) so that we can reproduce the behavior you are seeing on our end with your data set.
 
i) I am curious about what you meant by "tried with some success". If you could be more specific as to how the performance of the application changed with this approach, it would help us in narrowing down the problem. If you post a project, could you also provide the code for handling the BeforeDraw event that you implemented?
 
ii) No, it would not be more efficient to use the AnalogWaveform<UInt16> with the PlotWaveform method. Underneath the covers, we are handling the raw data as doubles.
Abhishek Ghuwalewala | Measurement Studio | National Instruments
0 Kudos
Message 2 of 7
(4,423 Views)
Hello Abhishek,

i have attached a zip file with the source code of a simple demo program which displays the samples from the file "data.dat"
(about a million samples). You can choose wether the default WaveformPlot class or the customized MyPlot class is used.

On my machine the zooming and panning is much more 'interactive' when using MyPlot instead of WaveformPlot.


Regards,
Jörg

0 Kudos
Message 3 of 7
(4,415 Views)

Thank you very much. The code you have supplied helped us immensely in narrowing down the problem. The problem has been fixed and will be available in the release of Measurement Studio after 8.1. In the meanwhile, you will need to continue using custom drawing (by overriding OnBeforeDraw) to draw the plot. You can also use the following decimation algorithm to further improve the performance of the drawing of MyPlot:

        protected static PointF[] Decimate(PointF[] points, int boundsWidth)
        {
            if (points.Length < boundsWidth * 2)
            {
                return points;
            }
            else
            {
                PointF[] decimatedPoints = new PointF[points.Length / 2];
                int j = 0;
                for (int i = 0; i < points.Length && j < decimatedPoints.Length; ++i)
                {
                    decimatedPoints[j++] = points[i];

                    if ((i + 1 < points.Length) && (points[i].X == points[i + 1].X))
                    {
                        float x = points[i].X;
                        float y = points[i].Y;
                        float first = y;
                        float last = y;
                        float min = y;
                        float max = y;

                        do
                        {
                            last = points[i + 1].Y;
                            min = Math.Min(min, last);
                            max = Math.Max(max, last);
                            ++i;
                        } while ((i + 1 < points.Length) && (x == points[i + 1].X));

                        if ((j < decimatedPoints.Length) && (max != first) && (max != last) && (max != min))
                        {
                            decimatedPoints[j++] = new PointF(x, max);
                        }
                        if ((j < decimatedPoints.Length) && (min != first) && (min != last))
                        {
                            decimatedPoints[j++] = new PointF(x, min);
                        }
                        if ((j < decimatedPoints.Length) && (last != first))
                        {
                            decimatedPoints[j++] = new PointF(x, last);
                        }
                    }
                }

                if (j >= decimatedPoints.Length)
                {
                    return points;
                }
                else
                {
                    PointF[] exactDecimatedPoints = new PointF[j];
                    Array.Copy(decimatedPoints, exactDecimatedPoints, j);
                    return exactDecimatedPoints;
                }
            }
        }

You can add a call to this Decimate function after calling MapDataPoints in your MyPlot.OnBeforeDraw.

Thanks.

Abhishek Ghuwalewala | Measurement Studio | National Instruments
0 Kudos
Message 4 of 7
(4,385 Views)
Thanks for the code. I didn't try it yet, but i will do later.

I am still working on the memory problem. With the MyPlot class i am able to display a graph with 4 million samples, but when i try more samples, things get difficult due to the high memory usage.

I thought about using a ushort array and avoiding to call the PlotY() method. Do you think this is somehow feasible?

Jörg

0 Kudos
Message 5 of 7
(4,371 Views)
I am not completely clear about what you mean when you say "avoiding to call the PlotY() method". Do you mean that you only want override OnBeforeDraw on the plot and draw the data yourself? If so, then other graph operations such as zooming and panning will not work as expected because the graph will have no data stored.
Abhishek Ghuwalewala | Measurement Studio | National Instruments
0 Kudos
Message 6 of 7
(4,368 Views)
It was just an idea because calling PlotY() with a large double array needs a lot of memory. My idea was something like to hold the data in a ushort array and to process the data somehow when they are to be drawn.

But it is of couse no option when we loose operations like zooming and panning.

Jörg

0 Kudos
Message 7 of 7
(4,354 Views)