cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Try the Materials Informatics Toolkit, which is designed to easily handle SMILES data. This and other helpful add-ins are available in the JMP® Marketplace
Choose Language Hide Translation Bar
saneal
Level III

Issues with reproducing custom row legend settings in JSL

I am trying to create this bivariate plot for each wafer I have in a string. It looks good except I would like to update the row legend with custom colors and markers since there are many different color options in FailCode to distinguish by. I cannot use the general color themes. Is there a way to create custom legend specifications that will be the same for each plot created all in JSL?

 

*I was trying to think of a way to update the script after making these changes and copying to my script. However, haven't had any luck.

 

Bivariate(
	Y( :YLoc ),
	X( :XLoc ),
	By(:Wafer),
	SendToReport(
		Dispatch(
			{},
			"Bivar Plot",
			FrameBox,
			{Marker Size( 6 ), Row Legend(
				FailCode,
				Color( 1 ),
				Color Theme( "Strong and Pastel Mix" ),
				Marker( 0 ),
				Marker Theme( "" ),
				Continuous Scale( 0 ),
				Reverse Scale( 0 ),
				Excluded Rows( 0 )
			)}
		)
	)
);

 

1 ACCEPTED SOLUTION

Accepted Solutions
ErraticAttack
Level VI

Re: Issues with reproducing custom row legend settings in JSL

You can create a customized legend from graph boxes inside of a col box inside of a table box.

 

For example, here I create a table holding the fail codes and the row-states to use for each one (you would probably want to set this in a global namespace for re-use in your code, and make the table private so it doesn't show).

 

Next I create two example data tables, one of which has only half of the fail codes defined.

 

Next I create two functions -- one does a smart sort so that consecutive legend entries are consecutive (i.e., so that "FailCode_1, FailCode_10, FailCode_2" gets sorted properly).  The second function plots the bivariates and adds a custom legend.

 

When you run this, notice how the colors and markers for each plot are the same for the same FailCode.  You would probably want to set the colors and markers for your code, this is simply an example.

 

Names Default to Here( 1 );

colors = {
	//{r,g,b}
	{1,0.5,0},
	{1,0,1},
	{0,1,1},
	{1,0,0},
	{0,1,0},
	{0,0,1},
	{0.7, 0.5, 0.3},
	{0.3, 0.5, 0.7},
	{0.5, 0.3, 0.7},
	{0.5, 0.7, 0.3},
	{0.7, 0.5, 0.7},
	{0.5, 0.7, 0.5},
	{0.3, 0.7, 0.7},
	{0.9, 0.1, 0.2},
	{0.3, 0.5, 0.6},
	{0.1, 0.3, 0.9},
	{0.5, 0.2, 0.0},
	{0.0, 0.7, 0.3},
	{0.4, 0.1, 0.2},
	{0.8, 0.5, 0.2},
	{0.2, 0.8, 0.5}
};

names = {
	"FailCode_0",
	"FailCode_1",
	"FailCode_2",
	"FailCode_3",
	"FailCode_4",
	"FailCode_5",
	"FailCode_6",
	"FailCode_7",
	"FailCode_8",
	"FailCode_9",
	"FailCode_10",
	"FailCode_11",
	"FailCode_12",
	"FailCode_13",
	"FailCode_14",
	"FailCode_15",
	"FailCode_16",
	"FailCode_17",
	"FailCode_18",
	"FailCode_19",
	"FailCode_20"
};

Eval( Eval Expr(
color table = New Table("Colors",
	<<New Column( "FailCode", "Character", <<Set Values( names ) ), 
	<<New Column( "States", "Row State", <<Set Each Value( Combine States( colors = Expr( colors ); Color State( colors[Row()] ), Marker State( Row() ) ) ) )
)
) );
color table:States << Copy to Row States();

table 1 = New Table( "DataExample1",
	<<New Column( "rows", "Numeric", <<Set Values( 1::1000 ) ),
	<<New Column( "Wafer", "Character", <<Set Each Value( "WAFER_" || Char( Random Integer( 1, 4 ) ) ) ),
	<<New Column( "FailCode", "Character", <<Set Each Value( "FailCode_" || Char( 2 * Random Integer( 1, 10 ) ) ) ),
	<<New Column( "Time", "Numeric", <<Set Each Value( Today() + Random Integer( 1, 1000 ) * 60 ), << Format( "y/m/d h:m:s", 22, 0 ) ),
	<<New Column( "Data", "Numeric", <<Set Each Value( Random Exp() ) )
);

table 2 = New Table( "DataExample1",
	<<New Column( "rows", "Numeric", <<Set Values( 1::5000 ) ),
	<<New Column( "Wafer", "Character", <<Set Each Value( "WAFER_" || Char( Random Integer( 1, 4 ) ) ) ),
	<<New Column( "FailCode", "Character", <<Set Each Value( "FailCode_" || Char( Random Integer( 1, 20 ) ) ) ),
	<<New Column( "Time", "Numeric", <<Set Each Value( Today() + Random Integer( 1, 1000 ) * 60 ), << Format( "y/m/d h:m:s", 22, 0 ) ),
	<<New Column( "Data", "Numeric", <<Set Each Value( Random Exp() ) )
);

//Here is where we set the row-states for the tables to plot. We don't want the bivariate function setting the row states. table 1 << Update( With( color table ), Match Columns( :FailCode = :FailCode ), Add Columns From Update Table( :States ) ); table 1:States << Copy to Row States(); table 1 << Delete Columns( "States" );
//again for the second table table 2 << Update( With( color table ), Match Columns( :FailCode = :FailCode ), Add Columns From Update Table( :States ) ); table 2:States << Copy to Row States(); table 2 << Delete Columns( "States" ); smart sort = Function( {list, return sort index = 0}, {args, function name, doc string, sorted list, i, j, var, val, ret}, sorted list = {}; For( i = 1, i <= N Items( list ), i++, j = 0; var = ""; While( Not( Is Missing( val = Num( Substr( list[i], Length( list[i] ) - j ) ) ) ) & j < Length( list[i] ), var = val; j++; ); sorted list[i] = Eval List( {Substr( list[i], 1, Length( list[i] ) - j ), var, i, j} ); ); sorted list = Sort List( sorted list ); If( return sort index == 0, For( i = 1, i <= N Items( list ), i++, list[i] = sorted list[i][1] || Right( Char( sorted list[i][2] ), sorted list[i][4], "0" ) ); , For( i = 1, i <= N Items( sorted list ), i++, If( sorted list[i][1] == "BASELINE", list[sorted list[i][3]] = 0 , list[sorted list[i][3]] = i ) ); ); list ); make bivariate = Function( {table, xcol, ycol, categorical, legend}, {Default Local}, legend items = Smart Sort( Associative Array( Column( table, legend ) ) << Get Keys ); n items = N Items( legend items ); legend marker box = Col Box( "" ); names = {}; For( i = 1, i <= n items, i++, Eval( Eval Expr( loc = color table << Get Rows Where( :FailCode == Expr( legend items[i] ) ) ) ); // here is a little fun magic to create a legend column out of graph boxes ob = Outline Box( "", gb = Graph Box( Frame Size( 14, 14 ), Y Scale( 0, 1 ), X Scale( 0, 1 ), SuppressAxes, Marker Seg( [0.5], [0.5], Row States( color table, Matrix( loc ) ) ) ) ); //make sure that all the padding and borders look right gb[Frame Box( 1 )] << Padding( Left( 0 ), Top( 0 ), Right( 0 ), Bottom( 0 ) ) << Border( Top, 0 ) << Border( Bottom, 0 ) << Border( Left, 0 ) << Border( Right, 0 ) << Marker Size( 3 ) << SetBackgroundFill( 0 ); gb[Border Box( 1 )] << Left( 0 ) << Top( 0 ) << Right( 0 ) << Bottom( 0 ) << Sides( 0 ); legend marker box << Append( ob ); Insert Into( names, legend items[i] ); ); legend name box = String Col Box( "FailCode", names ); Eval( Eval Expr( hlb = H List Box( Platform( table, //need to encapsulate the bivariate in a platform to ensure it uses the correct table biv = Bivariate( Y( Column( table, ycol ) ), X( Column( table, xcol ) ), By(Column( table, categorical )) ); ) , legend box = Table Box( legend marker box , legend name box ) ); ) ); Try( hlb[List Box( 2 )] << Set Horizontal( 1 ) ); legend box << Set Selectable Rows( 1 ) << Set Shade Alternate Rows( 0 ) << Set Shade Cells( 0 ) << Set Shade Headings( 0 ) << Set Column Borders( 0 ) << Set Row Borders( 0 ) << Set Underline Headings( 0 ); If( Num( Trim( Word( 1, JMP Version(), "." ) ) ) > 12, legend box << Set Column Group Borders( 0 ) << Set Heading Column Borders( 0 ); ); //Lastly we need to set the row change function so that clicking the legend does normal legend things. Eval( Eval Expr( legend box << Set Row Change Function( Function( {this}, table = Expr( table ); items = Expr( legend items ); rows = this << Get Selected Rows(); legend column = Expr( legend ); If( N Rows( rows ) == 0, table << Clear Select; Return( 0 ); ); vals = Insert( {}, items[rows] ); Eval( Parse( Eval Insert( "\[ table << Select Where( Contains( ^vals^, :Name("^legend column^") ) ) ]\" ) ) ) ) ) ) ); hlb ); Eval( Eval Expr( New Window( "test", <<On Close( color table = Expr( color table ); table 1 = Expr( table 1 ); table 2 = Expr( table 2 ); Try( Close( table 1, No Save ) ); Try( Close( table 2, No Save ) ); Try( Close( color table, No Save ) ); ) , V List Box( Outline Box( "", make bivariate( table 1, "time", "data", "Wafer", "FailCode" ) ) , Outline Box( "", make bivariate( table 2, "time", "data", "Wafer", "FailCode" ) ) ) ) ) );
Jordan

View solution in original post

2 REPLIES 2
ErraticAttack
Level VI

Re: Issues with reproducing custom row legend settings in JSL

You can create a customized legend from graph boxes inside of a col box inside of a table box.

 

For example, here I create a table holding the fail codes and the row-states to use for each one (you would probably want to set this in a global namespace for re-use in your code, and make the table private so it doesn't show).

 

Next I create two example data tables, one of which has only half of the fail codes defined.

 

Next I create two functions -- one does a smart sort so that consecutive legend entries are consecutive (i.e., so that "FailCode_1, FailCode_10, FailCode_2" gets sorted properly).  The second function plots the bivariates and adds a custom legend.

 

When you run this, notice how the colors and markers for each plot are the same for the same FailCode.  You would probably want to set the colors and markers for your code, this is simply an example.

 

Names Default to Here( 1 );

colors = {
	//{r,g,b}
	{1,0.5,0},
	{1,0,1},
	{0,1,1},
	{1,0,0},
	{0,1,0},
	{0,0,1},
	{0.7, 0.5, 0.3},
	{0.3, 0.5, 0.7},
	{0.5, 0.3, 0.7},
	{0.5, 0.7, 0.3},
	{0.7, 0.5, 0.7},
	{0.5, 0.7, 0.5},
	{0.3, 0.7, 0.7},
	{0.9, 0.1, 0.2},
	{0.3, 0.5, 0.6},
	{0.1, 0.3, 0.9},
	{0.5, 0.2, 0.0},
	{0.0, 0.7, 0.3},
	{0.4, 0.1, 0.2},
	{0.8, 0.5, 0.2},
	{0.2, 0.8, 0.5}
};

names = {
	"FailCode_0",
	"FailCode_1",
	"FailCode_2",
	"FailCode_3",
	"FailCode_4",
	"FailCode_5",
	"FailCode_6",
	"FailCode_7",
	"FailCode_8",
	"FailCode_9",
	"FailCode_10",
	"FailCode_11",
	"FailCode_12",
	"FailCode_13",
	"FailCode_14",
	"FailCode_15",
	"FailCode_16",
	"FailCode_17",
	"FailCode_18",
	"FailCode_19",
	"FailCode_20"
};

Eval( Eval Expr(
color table = New Table("Colors",
	<<New Column( "FailCode", "Character", <<Set Values( names ) ), 
	<<New Column( "States", "Row State", <<Set Each Value( Combine States( colors = Expr( colors ); Color State( colors[Row()] ), Marker State( Row() ) ) ) )
)
) );
color table:States << Copy to Row States();

table 1 = New Table( "DataExample1",
	<<New Column( "rows", "Numeric", <<Set Values( 1::1000 ) ),
	<<New Column( "Wafer", "Character", <<Set Each Value( "WAFER_" || Char( Random Integer( 1, 4 ) ) ) ),
	<<New Column( "FailCode", "Character", <<Set Each Value( "FailCode_" || Char( 2 * Random Integer( 1, 10 ) ) ) ),
	<<New Column( "Time", "Numeric", <<Set Each Value( Today() + Random Integer( 1, 1000 ) * 60 ), << Format( "y/m/d h:m:s", 22, 0 ) ),
	<<New Column( "Data", "Numeric", <<Set Each Value( Random Exp() ) )
);

table 2 = New Table( "DataExample1",
	<<New Column( "rows", "Numeric", <<Set Values( 1::5000 ) ),
	<<New Column( "Wafer", "Character", <<Set Each Value( "WAFER_" || Char( Random Integer( 1, 4 ) ) ) ),
	<<New Column( "FailCode", "Character", <<Set Each Value( "FailCode_" || Char( Random Integer( 1, 20 ) ) ) ),
	<<New Column( "Time", "Numeric", <<Set Each Value( Today() + Random Integer( 1, 1000 ) * 60 ), << Format( "y/m/d h:m:s", 22, 0 ) ),
	<<New Column( "Data", "Numeric", <<Set Each Value( Random Exp() ) )
);

//Here is where we set the row-states for the tables to plot. We don't want the bivariate function setting the row states. table 1 << Update( With( color table ), Match Columns( :FailCode = :FailCode ), Add Columns From Update Table( :States ) ); table 1:States << Copy to Row States(); table 1 << Delete Columns( "States" );
//again for the second table table 2 << Update( With( color table ), Match Columns( :FailCode = :FailCode ), Add Columns From Update Table( :States ) ); table 2:States << Copy to Row States(); table 2 << Delete Columns( "States" ); smart sort = Function( {list, return sort index = 0}, {args, function name, doc string, sorted list, i, j, var, val, ret}, sorted list = {}; For( i = 1, i <= N Items( list ), i++, j = 0; var = ""; While( Not( Is Missing( val = Num( Substr( list[i], Length( list[i] ) - j ) ) ) ) & j < Length( list[i] ), var = val; j++; ); sorted list[i] = Eval List( {Substr( list[i], 1, Length( list[i] ) - j ), var, i, j} ); ); sorted list = Sort List( sorted list ); If( return sort index == 0, For( i = 1, i <= N Items( list ), i++, list[i] = sorted list[i][1] || Right( Char( sorted list[i][2] ), sorted list[i][4], "0" ) ); , For( i = 1, i <= N Items( sorted list ), i++, If( sorted list[i][1] == "BASELINE", list[sorted list[i][3]] = 0 , list[sorted list[i][3]] = i ) ); ); list ); make bivariate = Function( {table, xcol, ycol, categorical, legend}, {Default Local}, legend items = Smart Sort( Associative Array( Column( table, legend ) ) << Get Keys ); n items = N Items( legend items ); legend marker box = Col Box( "" ); names = {}; For( i = 1, i <= n items, i++, Eval( Eval Expr( loc = color table << Get Rows Where( :FailCode == Expr( legend items[i] ) ) ) ); // here is a little fun magic to create a legend column out of graph boxes ob = Outline Box( "", gb = Graph Box( Frame Size( 14, 14 ), Y Scale( 0, 1 ), X Scale( 0, 1 ), SuppressAxes, Marker Seg( [0.5], [0.5], Row States( color table, Matrix( loc ) ) ) ) ); //make sure that all the padding and borders look right gb[Frame Box( 1 )] << Padding( Left( 0 ), Top( 0 ), Right( 0 ), Bottom( 0 ) ) << Border( Top, 0 ) << Border( Bottom, 0 ) << Border( Left, 0 ) << Border( Right, 0 ) << Marker Size( 3 ) << SetBackgroundFill( 0 ); gb[Border Box( 1 )] << Left( 0 ) << Top( 0 ) << Right( 0 ) << Bottom( 0 ) << Sides( 0 ); legend marker box << Append( ob ); Insert Into( names, legend items[i] ); ); legend name box = String Col Box( "FailCode", names ); Eval( Eval Expr( hlb = H List Box( Platform( table, //need to encapsulate the bivariate in a platform to ensure it uses the correct table biv = Bivariate( Y( Column( table, ycol ) ), X( Column( table, xcol ) ), By(Column( table, categorical )) ); ) , legend box = Table Box( legend marker box , legend name box ) ); ) ); Try( hlb[List Box( 2 )] << Set Horizontal( 1 ) ); legend box << Set Selectable Rows( 1 ) << Set Shade Alternate Rows( 0 ) << Set Shade Cells( 0 ) << Set Shade Headings( 0 ) << Set Column Borders( 0 ) << Set Row Borders( 0 ) << Set Underline Headings( 0 ); If( Num( Trim( Word( 1, JMP Version(), "." ) ) ) > 12, legend box << Set Column Group Borders( 0 ) << Set Heading Column Borders( 0 ); ); //Lastly we need to set the row change function so that clicking the legend does normal legend things. Eval( Eval Expr( legend box << Set Row Change Function( Function( {this}, table = Expr( table ); items = Expr( legend items ); rows = this << Get Selected Rows(); legend column = Expr( legend ); If( N Rows( rows ) == 0, table << Clear Select; Return( 0 ); ); vals = Insert( {}, items[rows] ); Eval( Parse( Eval Insert( "\[ table << Select Where( Contains( ^vals^, :Name("^legend column^") ) ) ]\" ) ) ) ) ) ) ); hlb ); Eval( Eval Expr( New Window( "test", <<On Close( color table = Expr( color table ); table 1 = Expr( table 1 ); table 2 = Expr( table 2 ); Try( Close( table 1, No Save ) ); Try( Close( table 2, No Save ) ); Try( Close( color table, No Save ) ); ) , V List Box( Outline Box( "", make bivariate( table 1, "time", "data", "Wafer", "FailCode" ) ) , Outline Box( "", make bivariate( table 2, "time", "data", "Wafer", "FailCode" ) ) ) ) ) );
Jordan
saneal
Level III

Re: Issues with reproducing custom row legend settings in JSL

Thank you! This is exactly what I needed. I was able to use the first part of your code to update my rowstates and then create a legend without selecting a color scheme (selecting none instead of pastel for instance) and it maintained my row states (by wafer) like I wanted. 

 

I am a bit new to JMP script so the smart sort and more complicated bivariate script was a bit hard to follow. Anyway you can clarify any of that just for future use? Thank you!