LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

RefreshGraph() slow when plotting many plots

I have a plot program where I zoom in by dragging a rectangle over the plot (click-drag creates a rectangle which varies when dragging).

I create the rectangle with PlotRectangle which only shows up after a RefreshGraph. When there are a lot of plots on the graph (50 to 100) then the refreshing takes something like half a second or more. This makes the rectangle redraw very slow (when a rectangle is supposed to follow the mouse moves, half a second is a lot). Is there a way in which only the rectangle is redrawn and not all the other plots on the graph as well? PlotRectangle() doesn't have a DRAW_IMMEDIATELY option.

Smooth update is on, as well as copy data. But disabling either one doesn't have any performance effect. Somebody suggested a SetSleepPolicy(NONE) but that doesn't make much difference either.

CVI 6.0 BTW.
0 Kudos
Message 1 of 9
(5,381 Views)
Hi Erwin.

Here is a CVI project I came across a few years ago, which (I believe) shows how you can achieve what you need. It gave acceptable performance when I tested it with 100 plots on the graph. You will note that RefreshGraph() is not called.

I don't recall where on the web I found this file, and I can't find it now, so I can't credit the author.

Hope this helps.
Colin.
Message 2 of 9
(5,369 Views)
The reason RefreshGraph isn't called is because the graph is refreshed automatically as the ATTR_REFRESH_GRAPH attribute is true for this graph. Setting it to false by adding
SetCtrlAttribute (hpanel, PANEL_GRAPH, ATTR_REFRESH_GRAPH, 0);
makes that the rectangle isn't drawn unless a RefreshGraph() is called.

If the REFRESH_GRAPH attribute is true, again the *whole* graph is refreshed when PlotRectangle() is called, not just the rectangle. So there's no performance increase either way. It is probably unavoidable to refresh all plots on the graph and not just the rectangle otherwise all the deleted rectangles would leave an empty spot on the screen.

Maybe in some future version of CVI it would be nice to implement something like a temporary storage of the bitmap of a graph. Then this bitmap could be stored before a rectangle was drawn, and each time the rectangle is redrawn (because it is being resized by the mouse) the original bitmap would be restored and the rectangle would be drawn over that, instead of drawing all the plots one by one. Maybe I will experiment a bit with a canvas which is temporarily drawn over the graph.

Anyway, thanks for the input, because any response is highly appreciated.
0 Kudos
Message 3 of 9
(5,337 Views)
I had a similar problem. In my program graphs in a graph control can be changed with the mouse at runtime.
To speed up the update time I set the graph control invisible, draw all graphs and set the control back to visible. It work´s perfectly
0 Kudos
Message 4 of 9
(5,332 Views)
Erwin,

Actually in CVI 7.0 there is an attribute that you can set that does pretty much just what you described in your last reply in this thread. You can use SetCtrlAttribute with ATTR_SMOOTH_UPDATE set to true. So if you did have a way to get a copy of 7.0...
0 Kudos
Message 5 of 9
(5,327 Views)
Smooth update is already present in 6.0, and I was already using it. However, I wrote "Maybe I will experiment a bit with a canvas which is temporarily drawn over the graph."

Well, "experiment a bit" became an understatement 🙂 I've made a program which does exactly this, and it works like a charm.

To demonstrate it I've extracted a part of it and adjusted it so that it will demonstrate the speed/slowness of a graph refresh with several settings, and also demonstrate drawing zoom rectangles in 2 different ways: on the graph itself as a plot, or on a canvas which is temporarily shown over the graph.

Enjoy.

Erwin Timmerman
Message 6 of 9
(5,301 Views)
The canvas trick works like a charm! Many thanks.


0 Kudos
Message 7 of 9
(5,277 Views)
This is a pretty cool example. Thanks for sharing your solution with us. I played around with it a little and added some code to handle graphs axes that have log scale enabled. All I did was change the GetGraphXYValueFromMouseCursorPos(). Im posting this incase someone needs it.


int GetGraphXYValueFromMouseCursorPos(int panel, int control, Point MousePos, Rect PlotArea, double *XValue, double *YValue)
{
int mapMode;

double XMin, XMax, YMin, YMax;
Point PixelPos;
double logBase = 10;

// Put the origin of { 0, 0 } in the lower left corner of the plot area
// (the mouse cursor has its origin in the upper left corner of the screen)
PixelPos.x = MousePos.x - PlotArea.left;
PixelPos.y = PlotArea.top + PlotArea.height - MousePos.y;

// get the axes min and max values
GetAxisScalingMode (panel, control, VAL_XAXIS, 0, &XMin, &XMax);
GetAxisScalingMode (panel, control, VAL_LEFT_YAXIS, 0, &YMin, &YMax);

GetCtrlAttribute (panel, GRAPHPANEL_GRAPH, ATTR_XMAP_MODE, &mapMode);

if(mapMode == VAL_LOG)
{
if(XMin <=0)
XMin = pow(logBase,-1);

XMin = log10(XMin);
XMax = log10(XMax);

*XValue = pow(logBase, XMin + (double)(PixelPos.x) * (XMax - XMin) / (double)PlotArea.width);
}else{

// calculate the output values
*XValue = XMin + (double)(PixelPos.x) * (XMax - XMin) / (double)PlotArea.width;
}


GetCtrlAttribute (panel, GRAPHPANEL_GRAPH, ATTR_YMAP_MODE, &mapMode);

if(mapMode == VAL_LOG)
{
if(YMin <=0)
YMin = pow(logBase,-1);

YMin = log10(YMin);
YMax = log10(YMax);

*YValue = pow(logBase, YMin + (double)(PixelPos.y) * (YMax - YMin) / (double)PlotArea.height);
}else{

// calculate the output values
*YValue = YMin + (double)(PixelPos.y) * (YMax - YMin) / (double)PlotArea.height;
}

return 1;
}


I can understand why RefreshGraph might take a while with a large dataset plotted on the graph, since it has to go thru the entire data and try and replot everything. But I'm sure there was some ways we could optimize the operation some more in future versions of CVI.
Bilal Durrani
NI
Message 8 of 9
(5,256 Views)
Actually, *I* need it!! 🙂

I already had the routine adapted for log scale (and reverse scale as well), but I wasn't really happy with the results of the calculation the way I did it, so I omitted it in the program. It was somewhat accurate, but not really and not all the time. I was going to ask for the correct calculation in the "How exactly are the X and Y values of a graph calculated" thread, but you've already answered my question now 🙂

So thank you!!

Erwin
0 Kudos
Message 9 of 9
(5,238 Views)