02-06-2013 07:10 AM
Hi, dear NI team.
I will describe my scenario shortly, and then I will tell you what is my problem.
Scenario
I have array of doubles, actually those are Y coordinates of some series of (X,Y) points.
X coordinates of those points can be calculated by X = pointIndex * 0.0000125 formula.
Meaning that those points are measurements made every 0.0000125 S.
And now I want to put those point on plot. To do so I am using WaveformGraph and WaveformPlot.
I set plot's default increment to be 0.0000125 and then I call PLotY function and give it the data array.
Sounds correct up until now?
Now, in my application I have a feature I call Graph Markers. (The feature is much more complicated then it is discribed in the following example)
Lets say that the user want to see all points that have Y > 1.0, So the user fills some parameters and press magic button.
I have a threshold value,so I call some function that runs over data array and finds all values that are greater than 1.0.
For each found value it saves the point index in some dictionary, hash or whatever has O(1) looking for this index.
Now I want my plot to show those exact points in some way differently from other points. To do it I give this plot some special PointStyle.
This point style is data dependent, and it should work fast, because I have a lot of points and it is a drawing event.
So, I thought it is quite good place to use the fact that I have constant X-distance between points.
In my custom point style Draw function I have point X coordinate, I can divide it by plot's default increment and get the point index with O(1).
Then I will take this index, check whether it is in the dictionary, mentioned above, and then I will decide on point's style.
So, I am marking the points without increasing drawing complexity order.
Problem
But, here comes the trouble!
I don't know what I am doing wrong, may be I do something wrong, but for me it seems like a bug.
Take a look at the attached example project.
Plot's default increment is set to be 0.0000125, but for some points I get args.X equal to something like 0.blabla000000000003 and this leads to faulty index calculation and wrong points are marked.
And I am asking, how the hell I am getting X coordinate of point with something in eighth sign after zero, if I was using 0.0000125 (7 signs after zero) as a default increment ???
Please, tell me what I am doing wrong, if I do.
If it is a bug, then I need to know when it will be fixed, and what are the ways to do my job with the same complexity order.
Note that O(n) searches have immense influence on application performance, since we are talking about drawing event of easily millions of points
Best regards, Artem
02-28-2013 10:48 AM
Hi IDCDeveloper,
Iv had a look at this problem. I assume the problem you are discribing is this shown in the attached image.
The question that i need to ask is whether it is necessary to have that number of trailing zeros as given in the code you sent? Could you not keep it to the decimal places you require?
Thanks,
03-03-2013 01:08 AM
Hi again.
First of all the 8th sign after zero is quite a requested level of accuracy in my application.
My X-axis is time, and my device is making measurements on 800kHz rate, which gives interval between adjacent points of 0.00000125S.
And I think that 800kHz is not the highest rate of devices that you target to service with your controls.
Now look, if I would get the same picture that you show me in attached image - I will find an easy solution to just ignore the "trash" that comes after 8th sign.
But in my project I get both "value + trash" and "value - trash" so that I have to round it.
And I simply can't allow my application to do rounding at every paint event of every point.
For now I do all I need in ugly manual way.
I have a set of points that have to be marked (painted in different way) and on every paint event of plot I just use System.Drawing instruments to draw what I need.
It is quite a waste of time. I am drawing above NI points so it is already O(N+K) where N is total number of points and K is marked points number.
And I have to translate coordinates of point to display coordinates.
So, guys, it does not burn in my project, but I think if you provide data dependent point styles, you have to care about exact data values in drawing events.
Regards, Artem.
03-04-2013 02:02 PM
Hey Artem,
I'm checking with our Product Support Engineer for Measurement Studio to find out what the specified precision of the plot increment is--it looks to me like the 0.00000125 is within the level of precision, but what I'm thinking is that the "trash" data on the very end is beyond the precision of the graph. We should be able to find out if this is expected behavior.
I've been looking through your code, and I'm not quite sure what logic you're using to determine which points to highlight--the way I understand it, your code is only highlighting points which are even multiples of your increment. Is this correct?
One possible solution that I can think of would be to store a variable of what the current plot index is. Since your method uses the logic of basically stating "the point at this index should be highlighted", could you store the current point index, and just check against that in your Draw function?
I hope this helps a bit, and I will let you know when I hear back about the precision of the plot increment to see if that might be contributing to the issue.
03-05-2013 12:53 AM
Hi
The code I have provided is just a demonstration of my problem. There is no logic whatsoever in it 🙂
I will try to explain the "marking" logic
First of all user makes some measurement to get the data from device. Since the devise samples data with rate of 800kH every data point has its X coordinate as multiple of 0.0000125.
Now, when the data is plotted already user can mark different points in many ways. He can click specific point and give it a name and color. He can mark many points by setting some analitycal condition. For example he can say that he wants to mark all points with Y value above 1.0, and those points should be red. There are many ways to mark points. But all of it not important. What is important is the result of users actions. As a result for each plot I have some dictionary that use point index as a key, and point color, name etc. as a value. So, if I have point index I can tell you the point color, name etc. with O(1). Now lets say that I am in draw event. I have to know if this point is marked or not, right? If yes, then I will apply the requested color. To check it I just need point index in data series. And here I was thinking about using the fact that X coordinate have to be multiple of default increment if my plot use default increment to plot data. I tried to get the index by simply dividing the X value by default increment and failed... By the way, may be I am missing something, but I havent found another way to get point index in draw event (some e.PointIndex doesn't exist). If yo have other sugestion - let me know.
If you have any other questions - just let me know, I will answer them asap.
Regards,
Artem
03-05-2013 01:06 PM
Artem,
I spoke with our Product Support Engineer for Measurement Studio and he confirmed that this is a floating-point rounding error inherent in the use of a float or double data type, which is prevalent in computing (a Google search for "floating point precision" will return many results). We're seeing the same issue here. There's an MSDN article on the issue which presents a very common workaround, and is extremely applicable to the situation: http://msdn.microsoft.com/en-us/library/c151dt3s%28v=vs.110%29.aspx
As you can see, by using the FLOAT_EQ function defined at the top of the sample code, you compare the two values to within a certain tolerance. As long as the tolerance is less than actual data values (and in this case it is, by several decimal places), this should work properly for your application.
Finally, here is a .NET implementation of the algorithm: http://stackoverflow.com/questions/1530069/comparing-floating-point-values
I hope this helps clear things up, and let us know if you need any more assistance!