cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • JMP 19 is here! See the new features at jmp.com/new.
  • Register to attend Discovery Summit 2025 Online: Early Users Edition, Sept. 24-25.
Choose Language Hide Translation Bar
SpannerHead
Level VI

Colour Plots by Pass and Fail

I have a script that plots metrics by wafer number.  If the wafer falls below a threshold of passing die, it is designated a fail.  Is there a way to have the colours of the plots reflect pass and fail aside from creating a separate grading column for each parameter?

 

SpannerHead_0-1750790204679.pngSpannerHead_1-1750790423441.png

 


Slán



SpannerHead
17 REPLIES 17
jthi
Super User

Re: Colour Plots by Pass and Fail

Transform column 

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

dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
ml = dt << Manage Limits(Process Variables(Column Group("Processes")), Invisible);
ml << Show Limits All;
ml << Save to Column Properties;
ml << Close window;



dt << Set Table Variable("CURCOL", "NPN1");
dt << Transform Column("Color", Numeric, Nominal,  // using New Column is way simpler and less error-prone
	Formula(
		specs = Column(:CURCOL) << Get Property("Spec Limits");
		Col Min(AsColumn(Column(:CURCOL)), :lot_id) > specs["LSL"] & Col Max(AsColumn(Column(:CURCOL)), :lot_id) < specs["USL"]
	)
);

gb = dt << Graph Builder(
	Size(528, 448),
	Show Control Panel(0),
	Variables(X(:lot_id), Y(:NPN1), Color(:Color)),
	Elements(Points(X, Y, Legend(3)))
);

cw = gb << Column Switcher(
	:NPN1,
	{:NPN1, :PNP1, :PNP2, :NPN2, :PNP3, :IVP1, :PNP4, :NPN3, :IVP2, :NPN4, :SIT1,
	:INM1, :INM2, :VPM1, :VPM2, :VPM3, :PMS1, :SNM1, :SPM1, :NPN5, :EP2, :ZD6,
	:PBA, :PLG, :CAP, :PBA3, :PLG2, :PNP5, :NPN6, :PNP6, :PNP7, :NPN7, :PNP8,
	:IVP3, :IVP4, :IVP5, :IVP6, :PNP9, :NPN8, :NPN9, :IVP7, :NPN10, :N_1, :PBA1,
	:WPR1, :B10, :PLY10, :VBE210, :VTN210, :VTP210, :SIT2, :SIT3, :INV2, :INV3,
	:INV4, :INV5, :FST1, :FST2, :RES1, :RES2, :PNM1, :PPM1, :FNM1, :FPM1, :FST3,
	:FST4, :RES3, :RES4, :A1, :B1, :A2N, :A2P, :A2P1, :IVP8, :IVP9, :DE_H1,
	:NF_H1, :ESM1, :ESM2, :ESP1, :YFU1, :VPM4, :PBA2, :PBB1, :LYA1, :LYB1, :DEM1,
	:DEP1, :NFM1, :PLY1, :VDP1, :VDP2, :SNW1, :RSP2, :PLY2, :RSP1, :VDP3, :PBL1,
	:PLG1, :VDP4, :SPW1, :VIA1, :INM3, :VPM5, :VPM6, :INM4, :VPM7, :M1_M1,
	:M2_M2, :P1_P1, :E2A1, :E2B1, :NPN11, :IVP10, :PNP10, :INM5, :VPM8, :VPM9,
	:INM6, :VPM10, :N2A1, :N2B1, :NM_L1, :P2A1, :P2B1, :PM_L1, :P1, :M1}
);


pre = Function({prevcol, curcol, switcher},
	1;
);
Eval(EvalExpr(
	post = Function({prevcol, curcol, switcher},
		Expr(dt) << Set Table Variable("CURCOL", curcol);
	);	
	:Color << Reset Transform();
));
handler = cw << Make Column Switch Handler(pre, post);

With new column

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

dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
ml = dt << Manage Limits(Process Variables(Column Group("Processes")), Invisible);
ml << Show Limits All;
ml << Save to Column Properties;
ml << Close window;



dt << Set Table Variable("CURCOL", "NPN1");
dt << New Column("Color", Numeric, Nominal, << Hide(1), << Exclude(1),
	<< Set Property("Value Colors", {0 = 67, 1 = 36}),
	Formula(
		specs = Column(:CURCOL) << Get Property("Spec Limits");
		Col Min(AsColumn(Column(:CURCOL)), :lot_id) > specs["LSL"] & Col Max(AsColumn(Column(:CURCOL)), :lot_id) < specs["USL"]
	)
);

gb = dt << Graph Builder(
	Size(528, 448),
	Show Control Panel(0),
	Variables(X(:lot_id), Y(:NPN1), Color(:Color)),
	Elements(Points(X, Y, Legend(3)))
);

cw = gb << Column Switcher(
	:NPN1,
	{:NPN1, :PNP1, :PNP2, :NPN2, :PNP3, :IVP1, :PNP4, :NPN3, :IVP2, :NPN4, :SIT1,
	:INM1, :INM2, :VPM1, :VPM2, :VPM3, :PMS1, :SNM1, :SPM1, :NPN5, :EP2, :ZD6,
	:PBA, :PLG, :CAP, :PBA3, :PLG2, :PNP5, :NPN6, :PNP6, :PNP7, :NPN7, :PNP8,
	:IVP3, :IVP4, :IVP5, :IVP6, :PNP9, :NPN8, :NPN9, :IVP7, :NPN10, :N_1, :PBA1,
	:WPR1, :B10, :PLY10, :VBE210, :VTN210, :VTP210, :SIT2, :SIT3, :INV2, :INV3,
	:INV4, :INV5, :FST1, :FST2, :RES1, :RES2, :PNM1, :PPM1, :FNM1, :FPM1, :FST3,
	:FST4, :RES3, :RES4, :A1, :B1, :A2N, :A2P, :A2P1, :IVP8, :IVP9, :DE_H1,
	:NF_H1, :ESM1, :ESM2, :ESP1, :YFU1, :VPM4, :PBA2, :PBB1, :LYA1, :LYB1, :DEM1,
	:DEP1, :NFM1, :PLY1, :VDP1, :VDP2, :SNW1, :RSP2, :PLY2, :RSP1, :VDP3, :PBL1,
	:PLG1, :VDP4, :SPW1, :VIA1, :INM3, :VPM5, :VPM6, :INM4, :VPM7, :M1_M1,
	:M2_M2, :P1_P1, :E2A1, :E2B1, :NPN11, :IVP10, :PNP10, :INM5, :VPM8, :VPM9,
	:INM6, :VPM10, :N2A1, :N2B1, :NM_L1, :P2A1, :P2B1, :PM_L1, :P1, :M1}
);


pre = Function({prevcol, curcol, switcher},
	1;
);
Eval(EvalExpr(
	post = Function({prevcol, curcol, switcher},
		Expr(dt) << Set Table Variable("CURCOL", curcol);
	);	
));
handler = cw << Make Column Switch Handler(pre, post);

And if no column switcher is necessary this can be made simpler (or more complicated, depending on how much JSL is written).

-Jarmo
hogi
Level XII

Re: Colour Plots by Pass and Fail


@jthi wrote:

Transform column 

View more...

Great idea to use a table variable as intermediate storage location for the column reference.
Expr(dt) - Nice trick!

As an alternative, one can store the transform column with the report (the standard way when it's generated via right click in the column list of the dialog window).

 

 

names default to here(1);
dt = current data table();
gb = Graph Builder(
	Transform Column(
		"Col",
		Nominal,
		Formula(
			specs = Column( :CURCOL ) << Get Property( "Spec Limits" );
			Col Min( As Column( Column( :CURCOL ) ), :lot_id ) > specs["LSL"] &
			Col Max( As Column( Column( :CURCOL ) ), :lot_id ) < specs["USL"];
		)
	),
	Variables( X( :lot_id ), Y( :PBA3 ), Color( :Col ) ),
	Elements( Points( X, Y ) ),
	Column Switcher(:PBA3,{:PBA3,:SPM1})
);

cs = current report()["Column Switcher"] << get scriptable object;

Eval(EvalExpr(
	post = Function({prevcol, curcol, switcher},
		Expr(dt) << Set Table Variable("CURCOL", curcol);
	);	
));
handler = cs << Make Column Switch Handler(1, post);


 

Re: Colour Plots by Pass and Fail

Hi @SpannerHead ,

 

I made a script that will test whether the mean of each wafer has exceeded the LSL or USL set as a column property, and will subsequently colour the rows based on a fail/pass - you can run this and the colours will come through to any of the reports in JMP (i.e. Graph Builder)

names default to here(1);
dt = Current Data Table();
dt<<clear select;
//get the limits

Spec_limits = dt:Y << get property( "Spec Limits" );
USL_val=try(spec_limits["usl"]);
LSL_val=try(spec_limits["lsl"]);


// Calculate the mean for each wafer group
Summarize( wafer_meangroup= By( :Wafer ),value_means= Mean( :Y ) );

failed_rows={}; //create a blank list that can store the rows that have failed

//add to an associative array
Assoc_array=associative array(wafer_meangroup,value_means); //get the association of wafer name to the mean value

//Run a for loop that checks every item in the wafer>mean list and sees if it exceeds the USL, if it does then it's inserted into the failed_rows list
for(i=1, i<=n items(Assoc_array),i++,
	if(Assoc_array[wafer_meangroup[i]]>=usl_val, insert into(failed_rows, get=dt<<get rows where(:Wafer==wafer_meangroup[i])), {};
));

//Run a for loop that checks every item in the wafer<mean list and sees if it exceeds the LSL, if it does then it's inserted into the failed_rows list
for(i=1, i<=n items(Assoc_array),i++,
	if(Assoc_array[wafer_meangroup[i]]<=lsl_val, insert into(failed_rows, get=dt<<get rows where(:Wafer==wafer_meangroup[i])), {};
));

write(failed_rows);

//Convert the failed rows list from a nested list to a continuous - probably an easier way to achieve this!
// Create a location to store the list
continuous_failed_Rows = {};

// Loop through each sublist in the nested list
for (i = 1, i <= N Items(failed_rows), i++,
    // Loop through each element in the sublist
    for (j = 1, j <= N Items(failed_rows[i]), j++, 
        // Insert each element into the continuous list
        Insert Into(continuous_failed_Rows, failed_rows[i][j]);
    )
    );
    

// Display the continuous list
Write(continuous_failed_Rows);



dt<<select rows(continuous_failed_Rows);
dt<<colors("red");
dt<<invert row selection;
dt<<colors("green");




“All models are wrong, but some are useful”
hogi
Level XII

Re: Colour Plots by Pass and Fail

does this script work with Column Switcher?

Re: Colour Plots by Pass and Fail

Hi @hogi ,

 

No,  I've left this so it's agnostic of the report that is being opened to allow for flexibility, instead referring just to the data table. You could easily create an additional script to this to pull out the currently displayed Y variable name in whichever report is being used and have the script update according to that or use 'Make Filter Change Handler' to trigger the script searching for a change to the name

 

Thanks,

Ben

“All models are wrong, but some are useful”
hogi
Level XII

Re: Colour Plots by Pass and Fail

Ah, I see.

This seems to change also the colors in all the other plots : (

Re: Colour Plots by Pass and Fail

Hi @hogi,

 

I've adapted the script to take advantage of the 'Graphics Scripts' you can apply to frameboxes to track what the column switcher is that is open and to then change the colour based on the Y being shown

 

names default to here(1);

//Setting up an example data set with some columns to work from - not needed for actual use
dt = Open("$SAMPLE_DATA/Variability Data/Wafer.jmp");
:"Y"n<<set property("Spec Limits", {LSL(75), USL(78)});
dt<<clear select;
dt:wafer<<set data type("Character");//Temporary change to this to become character - for nominal data would need to add a section to check data type and alter the script in a choice of two different expressions (a script for character and script for nominal)
dt<<New Column("Y2", "Numeric", "Continuous", Formula(Random Normal(20,10)));
:"Y2"n<<set property("Spec Limits", {LSL(0), USL(20)});

//Set up your initial graph/visualisation - this is set up for Graph builder but should be interchangable

gb_expr=gb=Graph Builder(
	Variables( X( :Wafer ), Y( :Y ) ),
	Elements( Points( X, Y, Legend( 5 ) ) ),
);

//Apply a column switcher
columnswitcher=gb<<Column Switcher( :Y, {:Y, :Y2} );//define your column names here

//Define the initial column name and create a blank for the previous column used in the switcher
col_name="Y";
previousColumn = "";

report(gb)[FrameBox(1)]<< add graphics script( ( checkAndRunScript();));//grab the current column name and run the method in run_expr;

// Function to check for changes and run the script
checkAndRunScript = function( {},
    currentColumn = columnSwitcher << get current;
    if (currentColumn != previousColumn,
        previousColumn = currentColumn;
        run_expr;
    ),
        -1;//return -1 if no changes happens = this is needed to stop the script running again and again
);


get_limits_expr=expr(
//get the limits

Spec_limits = dt:Y_name << get property( "Spec Limits" );
USL_val=try(spec_limits["usl"]);
LSL_val=try(spec_limits["lsl"]);
);

// Calculate the mean for each wafer group
get_means_expr=expr(Summarize( wafer_meangroup= By( :Wafer ),value_means= Mean(y_name) ););

checklist_Expr=expr(failed_rows={}; //create a blank list that can store the rows that have failed

//add to an associative array
Assoc_array=associative array(wafer_meangroup,value_means); //get the association of wafer name to the mean value

//Run a for loop that checks every item in the wafer>mean list and sees if it exceeds the USL, if it does then it's inserted into the failed_rows list
for(i=1, i<=n items(Assoc_array),i++,
	if(Assoc_array[wafer_meangroup[i]]>=usl_val, insert into(failed_rows, dt<<get rows where(:Wafer==wafer_meangroup[i])), {};
));


//Run a for loop that checks every item in the wafer<mean list and sees if it exceeds the LSL, if it does then it's inserted into the failed_rows list
for(i=1, i<=n items(Assoc_array),i++,
	if(Assoc_array[wafer_meangroup[i]]<=lsl_val, insert into(failed_rows, dt<<get rows where(:Wafer==wafer_meangroup[i])), {};
));

);

convertlist_Expr=expr(

//Convert the failed rows list from a nested list to a continuous - probably an easier way to achieve this!
// Create a location to store the list
continuous_failed_Rows = {};

// Loop through each sublist in the nested list
for (i = 1, i <= N Items(failed_rows), i++,
    // Loop through each element in the sublist
    for (j = 1, j <= N Items(failed_rows[i]), j++, 
        // Insert each element into the continuous list
        Insert Into(continuous_failed_Rows, failed_rows[i][j]);
    )
    );
    

// Display the continuous list
Write(continuous_failed_Rows););


colour_rows=expr(
dt<<select rows(continuous_failed_Rows);
dt<<colors("red");
dt<<invert row selection;
dt<<colors("green"););

get_col_name_expr=expr(Y_name=column(col_name));

run_expr=expr(
get_col_name_expr;
get_limits_expr;
get_means_expr;
checklist_Expr;
colour_rows;
);

Thanks,

Ben

“All models are wrong, but some are useful”
SpannerHead
Level VI

Re: Colour Plots by Pass and Fail

Maybe I need to think about this one differently.  Could I create a coherent table below the graph with wafer grading as opposed to a colour scheme?


Slán



SpannerHead

Recommended Articles