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
EstelleS
Level III

How to link graph selections with JSL?

Hi Everyone!

 

I am using Application Builder and I have several different plots I scripted using Graph Builder. Many of the graphs are using different data tables that have been operated on using Python and sent back into JMP. Because the data goes through significant processing in Python, these tables do not include any of the same variables. I am looking for a way to connect selections on these graphs (like if you select one of the legend labels and it grays out the non-selected items) using JSL.

 

For example, I am graphing my raw data and my "final product" data, which has greatly reduced dimensions and similar features are grouped together, so in Table1/Graph1 there may be 30 columns and in Table2/Graph2 there are only 3. If I have a list box with the Table2 variables and I select Variable1, I would like to be able to highlight Variable1 on Graph2, but also to highlight the relevant information in Graph1. I can determine the relevant columns/rows to highlight, but I haven't been able to find how to actually set those selections on the graph. It would also be great if I could select one of the legend labels on a graph (where it automatically grays out the non-selected items) and script something so that it selects the relevant info on the other graphs.

 

Is there a JSL line to highlight something on a graph like this?

1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: How to link graph selections with JSL?

I have never used Application Builder, but you could possibly user Row State Handlers.

Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");

dt_summary = dt << Summary(
	Group(:sex),
	Mean(:height),
	Mean(:weight),
	Freq("None"),
	Weight("None"),
	Link to original data table(0)
);

Eval(EvalExpr(f_summary = Function({a}, 
	f = dt_summary << Get Selected Rows;
	group_selected = dt_summary[f, "sex"];
	expr(dt) << Select Where(Contains(group_selected, :sex));
)));
rs_summary = dt_summary << make row state handler(f_summary);

nw = New Window("demo",
	gb1 = dt << Graph Builder(
		Size(529, 457),
		Show Control Panel(0),
		Variables(X(:weight), Y(:height), Color(:sex)),
		Elements(Points(X, Y, Legend(4)))
	),
	gb2 = dt_summary << Graph Builder(
		Size(535, 451),
		Show Control Panel(0),
		Variables(X(:sex), Y(:"Mean(height)"n), Y(:"Mean(weight)"n, Position(1))),
		Elements(Bar(X, Y(1), Y(2), Legend(4), Label("Label by Value")))
	);
);
nw << On Close(rs_summary = .);

Other option could be to use Graph Script:

Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");

dt_summary = dt << Summary(
	Group(:sex),
	Mean(:height),
	Mean(:weight),
	Freq("None"),
	Weight("None"),
	Link to original data table(0)
);

nw = New Window("demo",
	gb1 = dt << Graph Builder(
		Size(529, 457),
		Show Control Panel(0),
		Variables(X(:weight), Y(:height), Color(:sex)),
		Elements(Points(X, Y, Legend(4)))
	),
	gb2 = dt_summary << Graph Builder(
		Size(535, 451),
		Show Control Panel(0),
		Variables(X(:sex), Y(:"Mean(height)"n), Y(:"Mean(weight)"n, Position(1))),
		Elements(Bar(X, Y(1), Y(2), Legend(4), Label("Label by Value")))
	);
);

Eval(EvalExpr(Report(gb2)[FrameBox(1)] << Add Graphics Script(
	f = dt_summary << Get Selected Rows;
	group_selected = dt_summary[f, "sex"];
	expr(dt) << Select Where(Contains(group_selected, :sex));	
)));

One more option would be to use Virtual Joins but these would require you to have data tables saved somewhere.

-Jarmo

View solution in original post

12 REPLIES 12
jthi
Super User

Re: How to link graph selections with JSL?

I have never used Application Builder, but you could possibly user Row State Handlers.

Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");

dt_summary = dt << Summary(
	Group(:sex),
	Mean(:height),
	Mean(:weight),
	Freq("None"),
	Weight("None"),
	Link to original data table(0)
);

Eval(EvalExpr(f_summary = Function({a}, 
	f = dt_summary << Get Selected Rows;
	group_selected = dt_summary[f, "sex"];
	expr(dt) << Select Where(Contains(group_selected, :sex));
)));
rs_summary = dt_summary << make row state handler(f_summary);

nw = New Window("demo",
	gb1 = dt << Graph Builder(
		Size(529, 457),
		Show Control Panel(0),
		Variables(X(:weight), Y(:height), Color(:sex)),
		Elements(Points(X, Y, Legend(4)))
	),
	gb2 = dt_summary << Graph Builder(
		Size(535, 451),
		Show Control Panel(0),
		Variables(X(:sex), Y(:"Mean(height)"n), Y(:"Mean(weight)"n, Position(1))),
		Elements(Bar(X, Y(1), Y(2), Legend(4), Label("Label by Value")))
	);
);
nw << On Close(rs_summary = .);

Other option could be to use Graph Script:

Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");

dt_summary = dt << Summary(
	Group(:sex),
	Mean(:height),
	Mean(:weight),
	Freq("None"),
	Weight("None"),
	Link to original data table(0)
);

nw = New Window("demo",
	gb1 = dt << Graph Builder(
		Size(529, 457),
		Show Control Panel(0),
		Variables(X(:weight), Y(:height), Color(:sex)),
		Elements(Points(X, Y, Legend(4)))
	),
	gb2 = dt_summary << Graph Builder(
		Size(535, 451),
		Show Control Panel(0),
		Variables(X(:sex), Y(:"Mean(height)"n), Y(:"Mean(weight)"n, Position(1))),
		Elements(Bar(X, Y(1), Y(2), Legend(4), Label("Label by Value")))
	);
);

Eval(EvalExpr(Report(gb2)[FrameBox(1)] << Add Graphics Script(
	f = dt_summary << Get Selected Rows;
	group_selected = dt_summary[f, "sex"];
	expr(dt) << Select Where(Contains(group_selected, :sex));	
)));

One more option would be to use Virtual Joins but these would require you to have data tables saved somewhere.

-Jarmo
EstelleS
Level III

Re: How to link graph selections with JSL?

Thanks for the response, @jthi! I'm not sure these solutions are applicable in my case unless there is a way to determine the selected rows/columns/index/etc simply from a selection made on the graph. None of the data tables used in my App are visible for the user to make selections in... The idea is just to interface with the visualizations and the code does all of the manipulations on the tables behind the scenes.

 

I feel like there has to be some iteration of "<< Get Selected" for the graph selections, but I haven't found the right implementation in the scripting index. If there is a JSL line for that, then I think the "<< Add Graphics Script" idea you mentioned could work pretty well once the selections have been made!

txnelson
Super User

Re: How to link graph selections with JSL?

When points, or lines are selected in a Graph Builder, Bivariate, etc. graph, the rows associated with the selection are selected in the associated data table.  This is regardless of the table being visible or not.  Therefore, it is a fairly simple matter to implement a Row State Handler, which will run whenever a change in the selection of rows is detected.

Jim
EstelleS
Level III

Re: How to link graph selections with JSL?

Is there a way to use Row State Handlers in a way that a selection on Graph1 highlights relevant info on Graph2 and vice versa? I can get it to be one way or the other, but it seems like if I want to do both, it becomes some circular argument that freezes JMP up.... Is there a smart way to point both graphs/datatables to the other that doesn't result in circular arguments?

txnelson
Super User

Re: How to link graph selections with JSL?

All graphs that have been generated from the same data table, will automatically have their points, lines, etc. selected, when in one of the graphs has points, lines, etc. selected.

If the graphs are from 2 different tables, then a row state handler can be constructed for each of the data tables.  You are correct in your statement about a circular argument, however, how I have handled this is to set a flag in each of the handlers that prevents the continuation of the cycle.

Here is a simple piece of pseudo code that should give you an idea on how to set it up

// Pseudo code, not runnable

dt1 = data table( "one" );
dt2 = data table( "twO" );

f1 = Function( {a},
if(flag ==1,
flag = 0,
theRows = dt1 << get selected rows;
flag = 1;
dt2 << select rows(theRows);
);
rs = dt1 << make row state handler( f1 );

f2 = Function( {a},
if(flag ==1,
flag = 0,
theRows = dt2 << get selected rows;
flag = 1;
dt1 << select rows(theRows);
);
rs = dt2 << make row state handler( f2 );
Jim
EstelleS
Level III

Re: How to link graph selections with JSL?

Thanks so much for the reply, @txnelson ! Using flags is a good idea. Unfortunately, I'm still running into some recursion issues... I've messed around with different locations of the flag variable and with my limited understanding of the JSL I'm playing around with, this current syntax makes the most sense to me (almost exactly how your pseudo code is structured). Here is mine:

 

 

appNS:already_run=0;

Eval(EvalExpr(f1 = Function({a},
	If(appNS:already_run==1,
	appNS:already_run=0,
	rows = dt1 << Get Selected Rows;
	appNS:already_run=1;
	group_selected = dt1[rows, "index1"];
	expr(dt2) << Select Where(Contains(group_selected, :"index2"));
))));
rs1 = dt1 << Make Row State Handler(f1);

Eval(EvalExpr(f2 = Function({a}, If(appNS:already_run==1, appNS:already_run=0, rows = dt2 << Get Selected Rows; appNS:already_run=1; group_selected = dt2[rows, "index2"]; expr(dt1) << Select Where(Contains(group_selected, :"index1")); )))); rs2 = dt2 << Make Row State Handler(f2);

The above does work if I make selections via clicking the legend labels (yay!) and if I make singular selections via clicking individual markers on the plot (yay!), but enters a loop if I try to make selections via dragging a selection pane on the actual plot (which is my user's most likely scenario). Are my flag variables supposed to be different for each separate function? The only way I can currently get it to work as I've described is by using the same flag variable... Is there simply something I'm overlooking?

 

It also seems to somehow change my "already_run" flag variable if I even hover my mouse over the graph without clicking anything. Is this due to how the Row State Handler works?

 

 

I appreciate your help!

txnelson
Super User

Re: How to link graph selections with JSL?

I would use Show() statements to display the flag status in the log, and then do your dragging as see if you can determine where the timing issue is.

Jim
EstelleS
Level III

Re: How to link graph selections with JSL?

That's what I've been trying but I don't think I understand states/row state handler/flags well enough. I have attached a video of what I described above. The graph shown is related to f2 and dt2:

 

appNS:already_run=0;

Eval(EvalExpr(f1 = Function({a},
	Show(appNS:already_run);
If(appNS:already_run==1, appNS:already_run=0, rows = dt1 << Get Selected Rows; appNS:already_run=1; group_selected = dt1[rows, "index1"]; expr(dt2) << Select Where(Contains(group_selected, :"index2")); )))); rs1 = dt1 << Make Row State Handler(f1);

Eval(EvalExpr(f2 = Function({a},
Show(appNS:already_run); If(appNS:already_run==1, appNS:already_run=0, rows = dt2 << Get Selected Rows; appNS:already_run=1; group_selected = dt2[rows, "index2"];
Show(group_selected); expr(dt1) << Select Where(Contains(group_selected, :"index1")); )))); rs2 = dt2 << Make Row State Handler(f2);

At first I was thinking that dragging was causing an issue because the selection was changing with each new point added until the dragging was completed, but based on the "group_selected" output in the log, it doesn't even seem like the selection is changing. It seems to me that the looping is because of adding a new selection within the row state handler, but I'm not sure how to avoid this to achieve my goal of both graphs (and eventually more) pointing at each other.

 

Any suggestions are welcome.

jthi
Super User

Re: How to link graph selections with JSL?

 There is some not so fun things going on with Row State Handlers (I always try to avoid them them, as they don't work fairly bad in my opinion). Try to run the example I have provided by clicking single rows in Big Class and see JMP Log.

Names Default To Here(1);

dt1 = Open("$SAMPLE_DATA/Big Class.jmp");

dt2 = dt1 << Summary(
	Group(:sex),
	Mean(:height),
	Mean(:weight),
	Freq("None"),
	Weight("None"),
	Link to original data table(0)
);

Eval(Eval Expr(f1 = Function({a},
	rows = Loc(Expr(dt1) << Get Row States, 1);
	group_selected = Expr(dt1)[rows, "sex"];
	show(Expr(dt1) << Get Row States, a);
	Expr(dt2) << Select Where(Contains(group_selected, :sex), current selection("clear"));
	wait(1);
)));
rs1 = dt1 << Make Row State Handler(f1);

Eval(Eval Expr(f2 = Function({a},
	rows = Loc(Expr(dt2) << Get Row States, 1);
	show(Expr(dt2) << Get Row States, a);
	group_selected = Expr(dt2)[rows, "sex"];
//	Expr(dt1) << Select Where(Contains(group_selected, :sex));
)));
rs2 = dt2 << Make Row State Handler(f2);


dt1 << On Close(
	rs1 = .;
	rs2 = .;
	close(dt2, no save);
);
Clear Log();
-Jarmo