cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
burakbagdatli
Level III

Disable Graph Updates with Interaction

I have a data table with columns ox, oy, dx, and dy. For demonstration purposes, you can assume all columns are random with formula: Random Normal(0, 10). The real problem is a network with a list of coordinates.
I would like to draw lines between (ox, oy) and (dx, dy) and I can do this with either Graph Builder or Graph Box (example below). However, with every interaction, JMP redraws the lines which makes my visualization very slow (I have >10 000 rows in the data table). I tested this by adding a small random part to the origin and destination coordinates in the graph script and as soon as there's any interaction (e.g., using the Grabber tool and dragging the canvas, adjusting axes, resizing the graph, resizing the window), the lines do change. Is there a way to stop JMP updating the graph and rerunning the scripts?


I couldn't find a way in Graph Builder (I'd prefer to use this platform) or Graph Box. I found the

<< Graph Updating( Per Mouse Up );

message but it only has two options; there's no "don't update" option as far as I can tell. Also, I think that message doesn't work with Graph Box anyway.

 

 

Here's a minimal Graph Box example that can draw lines but the lines get updated with every interaction:

New Window( "Example",
	Graph Box(
		Frame Size( 300, 300 ),
		Pen Color( "Blue" );
		o_x = :ox << Get Values();
		o_y = :oy << Get Values();

		d_x = :dx << Get Values();
		d_y = :dy << Get Values();

		For( i=1, i<=N Items(o_x), i++,
			origin = Eval List({o_x[i]*Random Normal( 1, 0.1 ), o_y[i]*Random Normal( 1, 0.1 )});
			destination = Eval List({d_x[i]*Random Normal( 1, 0.1 ), d_y[i]*Random Normal( 1, 0.1 )});
			Line(origin, destination);
		);
	);
);

Reminder, I only added the Random Normal in that Graph Box script just to see if the lines are being recalculated. The real problem has fixed coordinates.

 

 

Bonus question: is there a way to add lines after the graph box has been constructed? I couldn't find it in the examples. I theorized that maybe they won't be updated with every mouse interaction but couldn't test it.

What we see of the real world is not the unvarnished real world but a model of the real world, constructed so it is useful for dealing with the real world. —Richard Dawkins
4 REPLIES 4

Re: Disable Graph Updates with Interaction

I think that the problem is that the frame box will automatically update whenever there is a change, so it is best to make all the changes before rendering. Also, you can vectorize the operations for speed, too, instead of explicitly iterating with the For() function. Graphic segments offer some advantages, too, but they are poorly documented at present.

 

See this approach:

 

Names Default to Here( 1 );

// origin
o_x = :ox << Get As Matrix;
o_y = :oy << Get As Matrix;
// destination
d_x = :dx << Get As Matrix;
d_y = :dy << Get As Matrix;

n = N Items( o_x );

// vectorize for line segments
seg = (o_x  J( n, 1, Random Normal( 1, 0.1 ))) || (o_y f:* J( n, 1, Random Normal( 1, 0.1 ))) ||
	(d_x  J( n, 1, Random Normal( 1, 0.1 ))) || (d_y f:* J( n, 1, Random Normal( 1, 0.1 )));

// plot segments
New Window( "Example",
	gb = Graph Box(
		Frame Size( 300, 300 ),
		Pen Color( "Blue" );
		Line Seg( seg );
	)
);

// later, update seg, then send gb << Reshow message to graph box

 

(I do not have your data table so I could not test it, but it should still illustrate the approach.)

burakbagdatli
Level III

Re: Disable Graph Updates with Interaction

I didn't know that I could do vectorization like that in JSL. So thanks for teaching me that method!

 

Once I move the randomness computation out of the graph box, the numbers don't update, but that's misleading. I only put the randomness in to convince myself that JMP was redrawing the graph. So while this method worked, it didn't quite do what I wanted to do. Once I pulled the randomness calculation into the graph box, all the lines were moving around still. But I definitely learned something along the way. Thanks!

 

Also, I still had to for loop the line drawing because my lines were not supposed to be connected paths. So, I couldn't just create a single pair of x and y matrices and pass them to Line or Line Seg.

 

I used your code to make it work with my data table and it's below. I'll attach the table to this message in case someone else needs this solution.

 

Names Default To Here( 1 );

// origin
o_x = :ox << Get As Matrix;
o_y = :oy << Get As Matrix;
// destination
d_x = :dx << Get As Matrix;
d_y = :dy << Get As Matrix;

n = N Items( o_x );


// plot segments
New Window( "Example",
	gb = Graph Box(
		Frame Size( 300, 300 ),
		Pen Color( "Blue" );
		seg_x = (o_x  J( n, 1, Random Normal( 1, 0.1 ) )) || (d_x  J( n, 1, Random Normal( 1, 0.1 ) ));
		seg_y = (o_y  J( n, 1, Random Normal( 1, 0.1 ) )) || (d_y  J( n, 1, Random Normal( 1, 0.1 ) ));
		For( i=1, i<=n, i++,
			Line( seg_x[i, -1], seg_y[i, -1] )
		)
	)
);
What we see of the real world is not the unvarnished real world but a model of the real world, constructed so it is useful for dealing with the real world. —Richard Dawkins
ErraticAttack
Level VI

Re: Disable Graph Updates with Interaction

IMHO JMP really really _VERY_ badly needs to update this functionality.  I've run into this issue multiple times and there is, quite simply, no valid work-around.  JMP should only re-run the graphics script when something changes (such as the size of the graph), not simply when scrolling / changing the size of the window.

 

That being said, I've found that the fastest method for doing something like this is as shown below.  I create an SVG path (in my experience this is hands-down the fastest way to render complex paths in JMP) and have a sentinel to determine whether or not to reconstruct the path.  I've included a button to force the reconstruction of the path simply as an example.

 

Hope this helps, but even better would be the JMP devs providing a system that behaves as all other display manager systems (including multi-threaded, signal/slots, callbacks, etc...).

 

I've also toyed around with using this method to grab an image of the desired render, check the size of the graphics box, and if the size hasn't changed, use the saved image as the thing to show.  This is what JMP should be doing and never ever should have been setup to aggressively execute the graphics script at every possible opportunity.  However, I've not had much luck with this method as JMP doesn't provide the necessary tools to make this work properly

 

self = New Namespace();
self:table = Current Data Table();
self:redraw = 1;
self:path = "";
self:build path = Function( {},
	{Default Local},
	self:path = "";
	For Each Row( self:table,
		self:path ||= Eval Insert( "\[M^:ox * Random Normal( 1, 0.1 )^,^oy * Random Normal( 1, 0.1)^ L^dx * Random Normal( 1, 0.1 )^,^:dy * Random Normal( 1, 0.1 )^]\" )
	);
);

Eval( Eval Expr(
New Window( "Example",
	<<On Close(
		self = Namespace( Expr( self << Get Name ) );
		self << Delete Namespace;
	)
,
	V List Box(
		Button Box( "Redraw",
			<<Set Function(
				Function( {this},
					{Default Local},
					
					self:redraw = 1;
					self:graph box << Inval;
				)
			)
		)
	,
		self:graph box = Graph Box(
			Frame Size( 300, 300 ),
			Pen Color( "Blue" );
			self = Namespace( Expr( self << Get Name ) );
			If( self:redraw,
				self:build path;
				self:redraw = 0
			);

			Path( self:path )
		);
	)
);
) );

 

Jordan
burakbagdatli
Level III

Re: Disable Graph Updates with Interaction

This is a really interesting idea. Unfortunately, with the 20K points the path had to go through with the Moves and Lines the graphics were struggling even more and it was even slower.

But I'll keep this in mind for future problems because I like the idea that there's technically a single path here and no loops are needed in the graphics code.

What we see of the real world is not the unvarnished real world but a model of the real world, constructed so it is useful for dealing with the real world. —Richard Dawkins