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

Graph box Frame Reference gets 'lost' when adding a graphics Script.

I am trying to draw a simple Wafermap which works fine with the following code.

However, when I substitute variables in for the numbers I get a missing reference error and can't for the life of me understand why this is happening. I need some JSL Expert Wisdom

 

F_makeWaferMap = function({myScale, myWhiteSpace, myWaferDiameter},{},

	myKeepOutZone = 2000;
	
	myGraphBox = graphBox( 
		frameSize( (myWaferDiameter/2)/myScale, (myWaferDiameter/2)/myScale ), 
		xScale( -myWhiteSpace, myWaferDiameter + myWhiteSpace),
		yScale( -myWhiteSpace, myWaferDiameter + myWhiteSpace)
					
	);
	frame = myGraphBox[FrameBox(1)];
	frame << Add Graphics Script(penColor( "red" ); circle( {150000,150000}, 150000));
	frame << Add Graphics Script(penColor( "red" ); circle( {150000,150000}, 150000-2000));
	
	return(myGraphBox);
);

myWmDispObj = F_makeWaferMap(200, 20000, 300000);		// Scale, Whitespace, Wafer Diameter
newWindow("Test", vListBox(myWmDispObj));

thickey_0-1647940685853.png

I am happily making references to the Frame Box as you can see from the log:

thickey_1-1647940813033.png

So, now lets substitute in some variables.

	frame << Add Graphics Script(penColor( "red" ); circle( {myWaferDiameter/2, myWaferDiameter/2}, myWaferDiameter/2));
	frame << Add Graphics Script(penColor( "red" ); circle( {myWaferDiameter/2, myWaferDiameter/2}, (myWaferDiameter/2) - myKeepOutZone));

And I get the following Error, suggesting I have lost the reference to my passed in variables when I try to add them to the frame box.

thickey_2-1647940929283.png

I'm stumped

 

 

7 REPLIES 7
jthi
Super User

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

You might have to use some Eval(EvalExpr()) magic Insert one expression into another using Eval Insert, Eval Expr, Parse, and Substitute 

	Eval(EvalExpr(
		frame << Add Graphics Script(
			Pen Color("red");
			Circle({Expr(myWaferDiameter) / 2, Expr(myWaferDiameter) / 2}, Expr(myWaferDiameter) / 2);
		);
	));
-Jarmo
thickey
Level III

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

Hi Jarmo, yes, I can simply do an eval(parse()), substituting my variable into the string to be converted to JSL but it's not the 'proper' way to go in my opinion.. Surely, there is a mechanism to this in a more ;direct' way.

 

 

 

eval(parse("frame << Add Graphics Script(penColor( \!"red\!" ); circle( {150000,150000}, " || char(myWaferDiameter/2) || "))"));
jthi
Super User

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

I would never use Evil(Parse()) if it can be avoided (and in this case it can be) by using Eval(EvalExpr()) or substitute. At least I don't know of any other methods besides these (or if I do they are more complicated), how I could replace values in some platforms/jmp functions with values (like in Formulas). My preferred method is EvalExpr() as it is fairly easy to debug and it still gives you JSL highlighting in script editor (parse method wont).

 

Names Default To Here(1);

F_makeWaferMap = function({myScale, myWhiteSpace, myWaferDiameter},{},

	myKeepOutZone = 2000;
	
	myGraphBox = graphBox( 
		frameSize( (myWaferDiameter/2)/myScale, (myWaferDiameter/2)/myScale ), 
		xScale( -myWhiteSpace, myWaferDiameter + myWhiteSpace),
		yScale( -myWhiteSpace, myWaferDiameter + myWhiteSpace)
					
	);
	frame = myGraphBox[FrameBox(1)];

	expr_sub = Substitute(
		Expr(frame << Add Graphics Script(
			penColor("red"); 
			circle({myWaferDiameter/2, myWaferDiameter/2}, myWaferDiameter/2)
		)),
		Expr(myWaferDiameter),
		myWaferDiameter
	);
	
	expr_evalexpr = EvalExpr(
		frame << Add Graphics Script(
			penColor( "red" ); 
			circle({Expr(myWaferDiameter)/2, Expr(myWaferDiameter)/2}, (Expr(myWaferDiameter)/2) - Expr(myKeepOutZone)));
	);
	
	show(expr_sub);
	show(expr_evalexpr);

	Eval(expr_sub);
	Eval(expr_evalexpr);
	
	return(myGraphBox);
);

myWmDispObj = F_makeWaferMap(200, 20000, 300000);		// Scale, Whitespace, Wafer Diameter
newWindow("Test", vListBox(myWmDispObj));
Show(myWmDispObj << Get Graphics Script);
-Jarmo
Craige_Hales
Super User

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

The parameter WaferDiameter in the function MakeWaferMap only exists while the function is running. The formula supplied to <<addGraphicsScript will be unhappy with that variable later, when the graph redraws and tries to use it.

I also like the eval(evalexpr( ... expr() ... expr() ... ) ) method for casting the transient variables into stone, mostly because the JSL editor will still do all of the syntax checking for ( and ).

Craige
Joseph_Reese
Level IV

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

Hello, I am not exactly sure why this works but would appreciate any insights. It seems that if you set another variable in your function (in this case just myWaferDiameter1) it seems to pass to the frame messages just fine?

 

Names Default to Here( 1 );

F_makeWaferMap = function({myScale, myWhiteSpace, myWaferDiameter},{},
	
	myWaferDiameter1 = myWaferDiameter; //new variable here?
	
	myKeepOutZone = 2000;
	
//Use myWaferDiameter1 instead myGraphBox = graphBox( frameSize( (myWaferDiameter1/2)/myScale, (myWaferDiameter1/2)/myScale ), xScale( -myWhiteSpace, myWaferDiameter1 + myWhiteSpace), yScale( -myWhiteSpace, myWaferDiameter1 + myWhiteSpace) ); frame = myGraphBox[FrameBox(1)];
frame << Add Graphics Script(penColor( "red" ); circle( {myWaferDiameter1/2, myWaferDiameter1/2}, myWaferDiameter1/2)); frame << Add Graphics Script(penColor( "red" ); circle( {myWaferDiameter1/2, myWaferDiameter1/2}, (myWaferDiameter1/2) - myKeepOutZone)); return(myGraphBox); ); myWmDispObj = F_makeWaferMap( 200, 20000, 300000 ); // Scale, Whitespace, Wafer Diameter newWindow("Test", vListBox( myWmDispObj ));
thickey
Level III

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

Joseph, I noticed this also but like you I don't understand why a locally (to the function) generated variable works, whereas one passed in does not. V.Interesting.

ih
Super User (Alumni) ih
Super User (Alumni)

Re: Graph box Frame Reference gets 'lost' when adding a graphics Script.

Hello @Joseph_Reese,

 

This works because variables defined inside the function are not, by default, local to that function. If you use delete symbols() before and show symbols() after running that script, you will find myWaferDiameter1 is now a global variable. Whenever writing functions I recommend using {defaultlocal} as the second argument for this reason, or to name all variables created in the function in that parameter so they are all local to that function call only.  If you use default local you will find the error re-appears since the variable no longer exists when the graph is drawn.  As @jthi points out, you can resolve this by evaluating the variable in the function context and then passing the value to the graph. As @Craige_Hales suggested, parameters to the function are also removed once the function finishes running, which is what caused the original problem.

 

So, to the original question from @thickey:

 

In the original example and when using a local variable in the function or as an argument to a function, the value myWaferDiameter exists in the function's local namespace until the function finishes running at which time it is removed from memory.  Since the graph is not drawn until after the function is finished running it cannot access the variable's value. To solve this, evaluate the variable in the context of the function.  I also prefer the method of doing this that @jthi described:

	Eval(EvalExpr(
		frame << Add Graphics Script(
			Pen Color("red");
			Circle({Expr(myWaferDiameter) / 2, Expr(myWaferDiameter) / 2}, Expr(myWaferDiameter) / 2);
		);
	));

 

When a variable is defined in the function that is a global variable, that variable exists until it is either deleted (using delete symbols() for example) or until JMP is restarted. So, when the window is drawn after the function finishes, it can still access the variable. This is a solution but it is more likely to cause errors in future code since different windows or scripts could interact with each other unexpectedly.

 

PS: As a shameless plug for my own wish list item, I think evaluating myWaferDiamer in right context can be made slightly more intuitive by introducing a new function: Introduce Eval Expr First() as a new wrapper for Eval( Eval Expr( ... ) )