cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
EstelleS
Level III

How to script all X and Y data to a single time-series graph in JMP Application?

Hi All,

 

I am developing a JMP Application that uses Python integration to give the application users the flexibility of loading in any (Excel) data file with industrial process data. This Application includes multiple module windows and extensive scripting.

 

One thing I am trying to do is to simply plot all of the data from a loaded data file onto one graph, where the first column is always time (X) and the remaining columns are the process variables (Y). I have built a module with a Graph Box to display this once the application runs and the data is loaded, but I am having trouble scripting this functionality. Because I don't know how many columns will be in any given data file, nor what they are titled, I need the script to automatically accept all the Y's (all data columns other than the first one) and pass that through the graph. 

 

Messing around with JMP's different graphing options, I have not been able to get Time Series graphs to show multiple overlaid plots, so I have been trying to script with Graph Builder. When I manually plot the data in Graph Builder, I can select all the columns I want and drag them onto the Graph Builder Y and it shows up how I want, with all the data shown on one plot. However, when I try to script this, Graph Builder only shows the first Y variable I pass through the script.

 

I am not sure how to solve this problem. Any advice/other suggestions are greatly appreciated!

 

Thank you!

- Estelle

 

P.S. If there is another way to graph this data in this way without using Graph Builder, please let me know. I prefer that this application only shows the user the graphed result and not all the additional functionality that is available when using Graph Builder.

1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: How to script all X and Y data to a single time-series graph in JMP Application?

Combining the solution me and @txnelson provided earlier you should be able to modify point/smoother and so on. First create the graph with JMP (no need to have all columns in y axis, you can use just two). I will go through the process how I would develop this script (this will be a bit long):

1. Open JMP sample data. In this case Semiconductor Capability.jmp as I know it has many columns

2. Create a graph in graph builder with some column as X axis and two as Y axis

jthi_0-1647974853736.png

Take the script

 

Graph Builder(
	Variables(X(:lot_id), Y(:NPN1), Y(:PNP1, Position(1))),
	Elements(Points(X, Y(1), Y(2), Legend(3)))
)

3. Change the points to line and I will also change Summary Statistic from default value, so I can see  how that can be changed in script

 

jthi_1-1647974925191.png

Take script

 

Graph Builder(
	Variables(X(:lot_id), Y(:NPN1), Y(:PNP1, Position(1))),
	Elements(Line(X, Y(1), Y(2), Legend(4), Summary Statistic("Median")))
)

4. Now I have quite good baseline scripts to start working on this. Because I know Re: Can you construct this without writing expression a string? can be used to solve this issue, I use that as my baseline (script I did provide earlier).

 

With basic graph:

 

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

x_col = Column(dt, 1);
y_cols = (dt << Get Column Names())[5::N Cols(dt)];

var_expr = EvalExpr(
	Variables(X(Expr(x_col))
));

For Each({col}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, NameExpr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
);

gb = Eval(Substitute(
	Expr(
		gb = dt << Graph Builder(
			Size(838, 391),
			Show Control Panel(0),
			vvv,
		)
	),
	Expr(vvv), Name Expr(var_expr),
));

gb_image = gb << get picture;
gb << Close Window;
New window("test",
	gb_image
);

Now If I wanted to have Line instead of points I would check what I have to change in the "line" script JMP gave me earlier. Basically I will need to add elements.

 

 

	Elements(Line(X, Y(1), Y(2), Legend(4), Summary Statistic("Median")))

Luckily these have been added in the other post

 

 

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

x_col = Column(dt, 1);
y_cols = (dt << Get Column Names())[5::N Cols(dt)];

var_expr = EvalExpr(
	Variables(X(Expr(x_col))
));


var_line = Expr(Line(X));

For Each({col, idx}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, NameExpr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
	
	yline_expr = Parse("Y("||char(idx)||")");
	Insert Into(var_line, Name Expr(yline_expr));
);

gb = Eval(Substitute(
	Expr(
		gb = dt << Graph Builder(
			Size(838, 391),
			Show Control Panel(0),
			vvv,
			Elements(yyy)
		)
	),
	Expr(vvv), Name Expr(var_expr),
	Expr(yyy), Name Expr(var_line)
));

gb_image = gb << get picture;
gb << Close Window;
New window("test",
	gb_image
);

 

jthi_2-1647975390032.png

(I didn't change summary statistics, but it should be fairly easy to change them by inserting few more expressions to var_line before creation of graph builder)

 

yline_expr = Expr(Legend(6));
Insert Into(var_line, Name Expr(yline_expr));
yline_expr = Expr(Summary Statistic("Median"));
Insert Into(var_line, Name Expr(yline_expr));

 

 

Knowing how to use Expr, Substitute, NameExpr and so on I have learned through these couple of posts in community Insert one expression into another using Eval Insert, Eval Expr, Parse, and Substitute,Expression Handling Functions: Part I - Unraveling the Expr(), NameExpr(), Eval(), ... Conundrum  and with lots and lots of trial and error (I still get confused with them, especially with Name Expr)

 

And finally,if I were to combine this script with the script you have (I would clean it up more, change order of expressions, most likely prefill column selectors and maybe provide option to select what type of graph to use, but this should give an idea):

View more...
Names Default To Here(1);

//the data table you want to operate on
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
 
//number of columns in the data table
numcol = N Col(dt);
  
selectorwindow = New Window("Column Selector",
	<<Modal,
	<<return result,
	Border Box(Left(3), top(2),
		V List Box(
			H List Box(
				V List Box(Panel Box("Select Columns", colListData = Filter Col Selector(dt, << character(0), nLines(Min(numcol, 10))))),
					
				Panel Box("Cast Selected Columns into Roles",
					Lineup Box(N Col(2), Spacing(3),
						Button Box("X, Columns", colListX << Append(colListData << GetSelected)),
						colListX = Col List Box(nLines(1), min items(1), "numeric"),
						Button Box("Y, Columns", colListY << Append(colListData << GetSelected)),
						colListY = Col List Box("numeric", min items(1)),

					)
				),
				Panel Box("Action",
					Lineup Box(N Col(1), 
					//OK Button
						Button Box("OK",
							x_col = colListX << get items;
							y_cols = colListY << get items;
						)
					)
				)
			)
		)
	)
);

If(selectorwindow["Button"] != 1,
	Throw("Cancel pressed")
);

var_expr = Eval Expr(Variables(X(Expr(x_col))));

var_line = Expr(Line(X));

For Each({col, idx}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, Name Expr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
	
	yline_expr = Parse("Y(" || Char(idx) || ")");
	Insert Into(var_line, Name Expr(yline_expr));
);

yline_expr = Expr(Legend(6));
Insert Into(var_line, Name Expr(yline_expr));
yline_expr = Expr(
	Summary Statistic("Median")
);
Insert Into(var_line, Name Expr(yline_expr));

gb = Eval(
	Substitute(
			Expr(
				gb = dt << Graph Builder(Size(838, 391), Show Control Panel(0), vvv, Elements(yyy))
			),
		Expr(vvv), Name Expr(var_expr),
		Expr(yyy), Name Expr(var_line)
	)
);

gb_image = gb << get picture;
gb << Close Window;
New Window("test", gb_image);
-Jarmo

View solution in original post

6 REPLIES 6
jthi
Super User

Re: How to script all X and Y data to a single time-series graph in JMP Application?

This topic might be helpful:

Re: Can you construct this without writing expression a string? 

 

Lots of expressions here, also you can use << Get picture to "remove functionalities" from graph builder

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

x_col = Column(dt, 1);
y_cols = (dt << Get Column Names())[5::N Cols(dt)];

var_expr = EvalExpr(
	Variables(X(Expr(x_col))
));

For Each({col}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, NameExpr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
);

gb = Eval(Substitute(
	Expr(
		gb = dt << Graph Builder(
			Size(838, 391),
			Show Control Panel(0),
			vvv,
		)
	),
	Expr(vvv), Name Expr(var_expr),
));

gb_image = gb << get picture;
gb << Close Window;
New window("test",
	gb_image
);
-Jarmo
EstelleS
Level III

Re: How to script all X and Y data to a single time-series graph in JMP Application?

Thank you for the reply and the "<<get picture" tip! This script does work for what I'm trying to do! 

 

One thing I don't see/understand is how to specify if I want this graph to use the Line or Smoother and Point or possibly some other combination of graph Elements, as I haven't decided what is best for my use. Is there a way to add that into this?

 

Thank you!

- Estelle

jthi
Super User

Re: How to script all X and Y data to a single time-series graph in JMP Application?

Combining the solution me and @txnelson provided earlier you should be able to modify point/smoother and so on. First create the graph with JMP (no need to have all columns in y axis, you can use just two). I will go through the process how I would develop this script (this will be a bit long):

1. Open JMP sample data. In this case Semiconductor Capability.jmp as I know it has many columns

2. Create a graph in graph builder with some column as X axis and two as Y axis

jthi_0-1647974853736.png

Take the script

 

Graph Builder(
	Variables(X(:lot_id), Y(:NPN1), Y(:PNP1, Position(1))),
	Elements(Points(X, Y(1), Y(2), Legend(3)))
)

3. Change the points to line and I will also change Summary Statistic from default value, so I can see  how that can be changed in script

 

jthi_1-1647974925191.png

Take script

 

Graph Builder(
	Variables(X(:lot_id), Y(:NPN1), Y(:PNP1, Position(1))),
	Elements(Line(X, Y(1), Y(2), Legend(4), Summary Statistic("Median")))
)

4. Now I have quite good baseline scripts to start working on this. Because I know Re: Can you construct this without writing expression a string? can be used to solve this issue, I use that as my baseline (script I did provide earlier).

 

With basic graph:

 

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

x_col = Column(dt, 1);
y_cols = (dt << Get Column Names())[5::N Cols(dt)];

var_expr = EvalExpr(
	Variables(X(Expr(x_col))
));

For Each({col}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, NameExpr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
);

gb = Eval(Substitute(
	Expr(
		gb = dt << Graph Builder(
			Size(838, 391),
			Show Control Panel(0),
			vvv,
		)
	),
	Expr(vvv), Name Expr(var_expr),
));

gb_image = gb << get picture;
gb << Close Window;
New window("test",
	gb_image
);

Now If I wanted to have Line instead of points I would check what I have to change in the "line" script JMP gave me earlier. Basically I will need to add elements.

 

 

	Elements(Line(X, Y(1), Y(2), Legend(4), Summary Statistic("Median")))

Luckily these have been added in the other post

 

 

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

x_col = Column(dt, 1);
y_cols = (dt << Get Column Names())[5::N Cols(dt)];

var_expr = EvalExpr(
	Variables(X(Expr(x_col))
));


var_line = Expr(Line(X));

For Each({col, idx}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, NameExpr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
	
	yline_expr = Parse("Y("||char(idx)||")");
	Insert Into(var_line, Name Expr(yline_expr));
);

gb = Eval(Substitute(
	Expr(
		gb = dt << Graph Builder(
			Size(838, 391),
			Show Control Panel(0),
			vvv,
			Elements(yyy)
		)
	),
	Expr(vvv), Name Expr(var_expr),
	Expr(yyy), Name Expr(var_line)
));

gb_image = gb << get picture;
gb << Close Window;
New window("test",
	gb_image
);

 

jthi_2-1647975390032.png

(I didn't change summary statistics, but it should be fairly easy to change them by inserting few more expressions to var_line before creation of graph builder)

 

yline_expr = Expr(Legend(6));
Insert Into(var_line, Name Expr(yline_expr));
yline_expr = Expr(Summary Statistic("Median"));
Insert Into(var_line, Name Expr(yline_expr));

 

 

Knowing how to use Expr, Substitute, NameExpr and so on I have learned through these couple of posts in community Insert one expression into another using Eval Insert, Eval Expr, Parse, and Substitute,Expression Handling Functions: Part I - Unraveling the Expr(), NameExpr(), Eval(), ... Conundrum  and with lots and lots of trial and error (I still get confused with them, especially with Name Expr)

 

And finally,if I were to combine this script with the script you have (I would clean it up more, change order of expressions, most likely prefill column selectors and maybe provide option to select what type of graph to use, but this should give an idea):

View more...
Names Default To Here(1);

//the data table you want to operate on
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
 
//number of columns in the data table
numcol = N Col(dt);
  
selectorwindow = New Window("Column Selector",
	<<Modal,
	<<return result,
	Border Box(Left(3), top(2),
		V List Box(
			H List Box(
				V List Box(Panel Box("Select Columns", colListData = Filter Col Selector(dt, << character(0), nLines(Min(numcol, 10))))),
					
				Panel Box("Cast Selected Columns into Roles",
					Lineup Box(N Col(2), Spacing(3),
						Button Box("X, Columns", colListX << Append(colListData << GetSelected)),
						colListX = Col List Box(nLines(1), min items(1), "numeric"),
						Button Box("Y, Columns", colListY << Append(colListData << GetSelected)),
						colListY = Col List Box("numeric", min items(1)),

					)
				),
				Panel Box("Action",
					Lineup Box(N Col(1), 
					//OK Button
						Button Box("OK",
							x_col = colListX << get items;
							y_cols = colListY << get items;
						)
					)
				)
			)
		)
	)
);

If(selectorwindow["Button"] != 1,
	Throw("Cancel pressed")
);

var_expr = Eval Expr(Variables(X(Expr(x_col))));

var_line = Expr(Line(X));

For Each({col, idx}, y_cols,
	y_expr = Expr(Y(Position(1)));
	Insert Into(y_expr, Name Expr(col), 1);
	Insert Into(var_expr, Name Expr(y_expr));
	
	yline_expr = Parse("Y(" || Char(idx) || ")");
	Insert Into(var_line, Name Expr(yline_expr));
);

yline_expr = Expr(Legend(6));
Insert Into(var_line, Name Expr(yline_expr));
yline_expr = Expr(
	Summary Statistic("Median")
);
Insert Into(var_line, Name Expr(yline_expr));

gb = Eval(
	Substitute(
			Expr(
				gb = dt << Graph Builder(Size(838, 391), Show Control Panel(0), vvv, Elements(yyy))
			),
		Expr(vvv), Name Expr(var_expr),
		Expr(yyy), Name Expr(var_line)
	)
);

gb_image = gb << get picture;
gb << Close Window;
New Window("test", gb_image);
-Jarmo
EstelleS
Level III

Re: How to script all X and Y data to a single time-series graph in JMP Application?

Thank you so much for the helpful info and advice. I really appreciate it!

txnelson
Super User

Re: How to script all X and Y data to a single time-series graph in JMP Application?

It sounds as if you are generating your JSL from scratch....like a Python programmer would do, rather than taking the interactive Graph Builder that you produced and then having JMP generate the JSL that will create the graph.  If I interactively create the below graph,

txnelson_0-1647963146602.png

By going to the red triangle and selecting "Script" it produces a script that handles both Y axis variables


Graph Builder(
	Size( 528, 448 ),
	Show Control Panel( 0 ),
	Variables( X( :age ), Y( :height ), Y( :weight, Position( 1 ) ) ),
	Elements(
		Points( X, Y( 1 ), Y( 2 ), Legend( 5 ) ),
		Smoother( X, Y( 1 ), Y( 2 ), Legend( 6 ) )
	),
	SendToReport(
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				5,
				Base( 0, 0, 0, Item ID( "height", 1 ) ),
				Base( 1, 0, 0, Item ID( "weight", 1 ) )
			)}
		)
	)
);

Now, if your issue is, that when you take a script like the one above, and are trying to expand it to handle as many Y columns as you need, that can sometimes require a bit more work.

Here is the same structure of a graph, but with many more Y columns

txnelson_1-1647963717828.png

Here is the expanded JSL that JMP produced to recreate the graph

Graph Builder(
	Size( 528, 458 ),
	Show Control Panel( 0 ),
	Variables(
		X( :Wafer ID in lot ID ),
		Y( :NPN1 ),
		Y( :PNP1, Position( 1 ) ),
		Y( :PNP2, Position( 1 ) ),
		Y( :NPN2, Position( 1 ) ),
		Y( :PNP3, Position( 1 ) ),
		Y( :IVP1, Position( 1 ) ),
		Y( :PNP4, Position( 1 ) )
	),
	Elements(
		Points(
			X,
			Y( 1 ),
			Y( 2 ),
			Y( 3 ),
			Y( 4 ),
			Y( 5 ),
			Y( 6 ),
			Y( 7 ),
			Legend( 3 )
		),
		Smoother(
			X,
			Y( 1 ),
			Y( 2 ),
			Y( 3 ),
			Y( 4 ),
			Y( 5 ),
			Y( 6 ),
			Y( 7 ),
			Legend( 4 )
		)
	),
	SendToReport(
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				3,
				Base( 0, 0, 0, Item ID( "NPN1", 1 ) ),
				Base( 1, 0, 0, Item ID( "PNP1", 1 ) ),
				Base( 2, 0, 0, Item ID( "PNP2", 1 ) ),
				Base( 3, 0, 0, Item ID( "NPN2", 1 ) ),
				Base( 4, 0, 0, Item ID( "PNP3", 1 ) ),
				Base( 5, 0, 0, Item ID( "IVP1", 1 ) ),
				Base( 6, 0, 0, Item ID( "PNP4", 1 ) )
			)}
		)
	)
);
Graph Builder(
	Size( 528, 458 ),
	Show Control Panel( 0 ),
	Variables(
		X( :Wafer ID in lot ID ),
		Y( :NPN1 ),
		Y( :PNP1, Position( 1 ) ),
		Y( :PNP2, Position( 1 ) ),
		Y( :NPN2, Position( 1 ) ),
		Y( :PNP3, Position( 1 ) ),
		Y( :IVP1, Position( 1 ) ),
		Y( :PNP4, Position( 1 ) )
	),
	Elements(
		Points(
			X,
			Y( 1 ),
			Y( 2 ),
			Y( 3 ),
			Y( 4 ),
			Y( 5 ),
			Y( 6 ),
			Y( 7 ),
			Legend( 3 )
		),
		Smoother(
			X,
			Y( 1 ),
			Y( 2 ),
			Y( 3 ),
			Y( 4 ),
			Y( 5 ),
			Y( 6 ),
			Y( 7 ),
			Legend( 4 )
		)
	),
	SendToReport(
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				3,
				Base( 0, 0, 0, Item ID( "NPN1", 1 ) ),
				Base( 1, 0, 0, Item ID( "PNP1", 1 ) ),
				Base( 2, 0, 0, Item ID( "PNP2", 1 ) ),
				Base( 3, 0, 0, Item ID( "NPN2", 1 ) ),
				Base( 4, 0, 0, Item ID( "PNP3", 1 ) ),
				Base( 5, 0, 0, Item ID( "IVP1", 1 ) ),
				Base( 6, 0, 0, Item ID( "PNP4", 1 ) )
			)}
		)
	)
);

This is where the JSL programmer has to create the command string to execute to pass to Graph Builder.  If you are already doing this, and you are only getting the 1st Y variable in the graph, then typically what is happening is that Graph Builder isn't able to evaluate the information being passed to it.  If you provide the JSL you are using, the Community is usually pretty good at helping.  

 

 

 

 

Jim
EstelleS
Level III

Re: How to script all X and Y data to a single time-series graph in JMP Application?

Thanks for the reply! I have tried using the JMP-generated script and adjusting that, but I still get this issue. Below is a script that I've been working on to see what results I can get:

 

//the data table you want to operate on
datafile = Open( "Data.xlsx");
 
//number of columns in the data table
numcol = ncol(datafile);
  
selectorwindow = New Window("Column Selector", /*<<Modal*/,
    BorderBox(left(3),top(2),
        VListBox(
            HListBox(
                VListBox(
                    PanelBox("Select Columns",
                        colListData=ColListBox(datafile, All, nLines(min(numcol,10)))
                    )
                ),
					
                PanelBox("Cast Selected Columns into Roles",
                    LineupBox(NCol(2),Spacing(3),
                        ButtonBox("X, Columns", colListX<<Append(colListData<<GetSelected)),
						colListX = ColListBox(nLines(1),"numeric"),
						ButtonBox("Y, Columns", colListY<<Append(colListData<<GetSelected)),
						colListY = ColListBox("numeric"),
                    )
                ),
					
                PanelBox("Action",
					LineupBox(NCol(1),
					//OK Button
						ButtonBox("OK",
						//script that executes upon clicking "OK"
							Graph Builder(
								Variables(
									X(Eval(colListX << GetItems)),
									Y(Eval(colListY << GetItems))
								),
								Elements(
									Line( X, Y( 1 ), Y( 2 ), Legend( 1 ) ) 
								)
							)
						)
					)
				)
            )
        )
	)
);

I believe one of my issues may be in that I am not exactly sure how to specify the "Elements" portion to accept any number of Y's. For this specific script, no matter if I add more Elements( Line (Y(1), Y(2), Y(3), etc )) and change the columns I select as Y, I still only get one plotted variable.

 

Thanks!

- Estelle