cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
New to using JMP? Hit the ground running with the Early User Edition of Discovery Summit. Register now, free of charge.
Register for our Discovery Summit 2024 conference, Oct. 21-24, where you’ll learn, connect, and be inspired.
Choose Language Hide Translation Bar
SDF1
Super User

JSL: How to correctly pass variable values from one Expr() to another Expr()

Hi All,

 

  I'm having difficulty with variables that evaluate normally in one Expr1() not evaluating properly in another Expr2() that calls the first Expr. I have some code where I've defined an Expr1() that generates distributions of columns of interest. I have another expression later on, Expr2() that calls back to Expr1(). There are variables in Expr1() that appear not to evaluate properly in Expr2().

 

  For a visual, Expr2() generates a window that looks like the following:

SDF1_0-1697568386614.png

  The first expression, Expr1() is what generates the included Distribution platform below the graph builder. The combo box and button boxes below the distributions allow the user to switch between different fit statistics, such as different R^2, RMSE, Mean Abs Dev, -Logliklihood, etc. My intent is to update both the GB and Distribution accordingly. The GB updates appropriately, but the Distribution does not. When changing the Fit Statistic to RMSE, for example, this is the outcome:

SDF1_1-1697568723254.png

  It does update the Distribution graphs, but it uses their default size setting and not the size setting I've established within Expr1(). it's supposed to look like this where the distribution graphs are the same size as in the first image:

SDF1_2-1697568960505.png

  The section of code in Expr1() where the Distributions are generated is the following:

//this part gets column names to insert into Dispatch() below
sfitcol1 = Column( NNYCol + NNcolshift ) << Get Name; sfitcol2 = Column( NNYCol + 1 + NNcolshift ) << Get Name; sfitcol3 = Column( NNYCol + 2 + NNcolshift ) << Get Name;

//in this example, the results are:
//"RMSE Training"
//"RMSE Validation"
//"RMSE Test"
//this part generates the Distributions that will be used to change my output report in Expr2() dt_results << Distribution( Continuous Distribution( Column( Eval( NNYCol + NNcolshift ) ), Quantiles( 0 ) ), Continuous Distribution( Column( Eval( NNYCol + 1 + NNcolshift ) ), Quantiles( 0 ) ), Continuous Distribution( Column( Eval( NNYCol + 2 + NNcolshift ) ), Quantiles( 0 ) ), SendToReport( Dispatch( {sfitcol1}, "Distrib Histogram", FrameBox, {Frame Size( 60, 100 )} ), Dispatch( {sfitcol1}, "Distrib Outlier Box", FrameBox, {Frame Size( 30, 100 )} ), Dispatch( {sfitcol2}, "Distrib Histogram", FrameBox, {Frame Size( 60, 100 )} ), Dispatch( {sfitcol2}, "Distrib Outlier Box", FrameBox, {Frame Size( 30, 100 )} ), Dispatch( {sfitcol3}, "Distrib Histogram", FrameBox, {Frame Size( 60, 100 )} ), Dispatch( {sfitcol3}, "Distrib Outlier Box", FrameBox, {Frame Size( 30, 100 )} ) ) );

  If I run the Expr1() on it's own, it works just fine, the problem is when Expr2() calls Expr1() that it fails because of how it's not evaluating the variables sfitcol# in Dispatch, so it's not changing the FrameBox size as it's supposed to in the code.

  The section of code in Expr2() that swaps out the distributions (using the combo box only) is below:

NNycb = Combo Box(
	NNylist,
	<<Set( 1 ),
	<<Set Function(
		Function( {},
			NNycol = NNycb << Get;
			NNxcol = NNxcb << Get;
			NNgb << delete;
			NNd << delete;
			NNrob << Sib Prepend( NNgb = NNgb_change );
			NNlbcontent << Sib Prepend( NNd = NNdist_change );//this is where Expr2() calls Expr1(), NNdist_change
		)
	)
)

  Playing around with putting the part of Expr1() in the Combo Box function and then trying to run the sfitcol variables and then sending to the report to modify the frame box gives this error in the embedded log:

 

Cannot find item "sfitcol1" in outline context {sfitcol1}
Cannot find item "sfitcol1" in outline context {sfitcol1}
Cannot find item "sfitcol2" in outline context {sfitcol2}
Cannot find item "sfitcol2" in outline context {sfitcol2}
Cannot find item "sfitcol3" in outline context {sfitcol3}
Cannot find item "sfitcol3" in outline context {sfitcol3}

 

  If I then manually enter in the column name, for example with the first Dispatch: Send to Report(Dispatch({"RMSE Training"}, "Distrib Histogram", Framebox, Frame Size{(60,100)}), then it will change the frame box accordingly.

SDF1_3-1697570508054.png

 

  So, it's possible, and should work through how I've defined things in Expr1(), but the variable and not the value(text) of the variable is passed when executing things in Expr2(). Hoping to get some suggestions on how to correct this. I don't think I need to use an Eval(Substitute(Expr())) type solution, but perhaps I do.

 

  Any thoughts/ideas/suggestions are much appreciated.

 

Thanks!,

DS

1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: JSL: How to correctly pass variable values from one Expr() to another Expr()

I would avoid setting the frame sizes when creating the distributions and change them after distributions have been created. As you are setting specific frameboxes to specific sizes this should be fairly easy using XPath to get the references and then changing the sizes.

Names Default To Here(1);

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

dist = dt << Distribution(
	Continuous Distribution(Column(:height), Quantiles(0)),
	Continuous Distribution(Column(:weight), Quantiles(0))	
);

wait(1); // demo purposes

rep = Report(dist);
(rep << XPath("//FrameBox[@helpKey='Distrib Histogram']")) << Frame Size(60, 100);
(rep << XPath("//FrameBox[@helpKey='Distrib Outlier Box']")) << Frame Size(30, 100);
wait(0);

dist << get xml;

Regarding the issue you are facing, I would have to write test script to be sure, but my guess is that you should evaluate those values there.

-Jarmo

View solution in original post

3 REPLIES 3
jthi
Super User

Re: JSL: How to correctly pass variable values from one Expr() to another Expr()

I would avoid setting the frame sizes when creating the distributions and change them after distributions have been created. As you are setting specific frameboxes to specific sizes this should be fairly easy using XPath to get the references and then changing the sizes.

Names Default To Here(1);

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

dist = dt << Distribution(
	Continuous Distribution(Column(:height), Quantiles(0)),
	Continuous Distribution(Column(:weight), Quantiles(0))	
);

wait(1); // demo purposes

rep = Report(dist);
(rep << XPath("//FrameBox[@helpKey='Distrib Histogram']")) << Frame Size(60, 100);
(rep << XPath("//FrameBox[@helpKey='Distrib Outlier Box']")) << Frame Size(30, 100);
wait(0);

dist << get xml;

Regarding the issue you are facing, I would have to write test script to be sure, but my guess is that you should evaluate those values there.

-Jarmo
SDF1
Super User

Re: JSL: How to correctly pass variable values from one Expr() to another Expr()

Hi @jthi ,

 

  Thanks again for a quick response and solution to my issue. The XPath command is really cool, and I can see by just reading the brief Scripting Index entry on it, that I need to read up more about XPath and how to get more out of it. On a side note, has this been discussed in the Scripter's Club yet? If not, that could be a good topic.

 

  Anyway, I modified your code to be closer to the situation that I have at hand, and it works just fine. See the modified version below, which has Expr2 calling Expr1, and then inside Expr2, is the change for the distribution frame size.

Names Default To Here( 1 );

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

Expr1 = Expr(
	dist = dt << Distribution(
		Continuous Distribution( Column( :height ), Quantiles( 0 ) ),
		Continuous Distribution( Column( :weight ), Quantiles( 0 ) )
	)
);

Expr2 = Expr(
	Nwin = New Window( "Dists", Outline Box( "Results", Expr1 ) );
	Wait( 1 ); // demo purposes
	(Report( dist ) << XPath( "//FrameBox[@helpKey='Distrib Histogram']" )) << Frame Size( 60, 100 );
	(Report( dist ) << XPath( "//FrameBox[@helpKey='Distrib Outlier Box']" )) << Frame Size( 30, 100 );
);

Expr2;

  One thing to note for anyone that might not know this is that you can't have the XPath portion of the code within the New Window() object.

(Report( dist ) << XPath( "//FrameBox[@helpKey='Distrib Histogram']" )) << Frame Size( 60, 100 );
(Report( dist ) << XPath( "//FrameBox[@helpKey='Distrib Outlier Box']" )) << Frame Size( 30, 100 );

  That portion of the code has to be outside the New Window. In my particular case, I found out that I needed to include it as part of the function when the combo box or Prev/Next buttons are pushed, otherwise it resizes the Distributions to their original size. For example, for the Combo Box option, it looks like:

NNycb = Combo Box(
	NNylist,
	<<Set( 1 ),
	<<Set Function(
		Function( {},
			NNycol = NNycb << Get;
			NNxcol = NNxcb << Get;
			NNgb << delete;
			NNd << delete;
			NNrob << Sib Prepend( NNgb = NNgb_change );
			NNlbcontent << Sib Prepend( NNd = NNdist_change );
			(Report( NNd ) << XPath( "//FrameBox[@helpKey='Distrib Histogram']" )) << Frame Size( 60, 100 );
			(Report( NNd ) << XPath( "//FrameBox[@helpKey='Distrib Outlier Box']" )) << Frame Size( 30, 100 );
		)
	)
);

  There is a brief moment where the distributions are resized to their default when first Prepended to the Window, but then they're correctly resized very quickly.

 

  Thanks again for the help, and I always appreciate learning new things in the JMP Discussion forum.

 

Thanks!,

DS

jthi
Super User

Re: JSL: How to correctly pass variable values from one Expr() to another Expr()

I think I did cover XPath very shortly on Session 7 (report layer), but I think accessing and traversing report layer is good topic for other longer session. Xpath is basically its own language and one of the skills which translates directly over from JSL to other programming languages (regex is other example) XPath Tutorial (w3schools.com) . When accessing report layer in JMP using << XPath you are able to easily get a list of references and you can send messages to the list which makes it very useful. You can build robust "paths" (basically get references) to different display boxes when you combine << Get XML with << XPath.

-Jarmo