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
AT
AT
Level V

how to calculate yield for many columns with embedded spec limits

Hi,

I have over 60 columns where individual spec limits are embeded in column properties. I like to calculate the yield for each row as Pass/Fail. I appreciate any script that will do this. I checked the JMP discussion and found one script that does yield but each columns is assumed to be pass or fail (1 or 0). Thanks

1 ACCEPTED SOLUTION

Accepted Solutions
txnelson
Super User

Re: how to calculate yield for many columns with embedded spec limits

My error, an ")" was left out of the last statement.  It should be:

Eval( Parse( "dt << New Column( \!"Row Pass/Fail\!", formula( If( Min(" || foundCols || " ) == 1, 1, 0 ) ))" ) );
Jim

View solution in original post

17 REPLIES 17
txnelson
Super User

Re: how to calculate yield for many columns with embedded spec limits

Here is a script that will create new columns that numerically contain 0/1 and display as Fail/Pass

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

// Get all numeric columns
colList = dt << get column names( numeric, string );

foundCols = "";

// Loop across the columns and generate the test pass/fails
For( i = 1, i <= N Items( colList ), i++,
	spec = Column( dt, colList[i] ) << get property( "Spec Limits" );
	dt << clear select;
	If( Is Empty( spec ) == 0,
		dt << New Column( (Column( dt, colList[i] ) << get name) || " Pass/Fail" );
		If( Is Missing( Try( spec["LSL"], . ) ) == 0,
			dt << select where( As Column( dt, colList[i] ) < spec["LSL"] );
			Try( Column( dt, N Cols( dt ) )[dt << get selected rows] = 0 );
		);
		If( Is Missing( Try( spec["USL"], . ) ) == 0,
			dt << select where( As Column( dt, colList[i] ) > spec["USL"], current selection( "extend" ) );
			Try( Column( dt, N Cols( dt ) )[dt << get selected rows] = 0 );
		);
		dt << invert row selection;
		Try( Column( dt, N Cols( dt ) )[dt << get selected rows] = 1 );
		Column( dt, N Cols( dt ) ) << set property( "Value Labels", {0 = "Fail", 1 = "Pass"} );
		If( foundCols == "",
			foundCols = ":Name(\!"" || (Column( dt, colList[i] ) << get name) || " Pass/Fail\!")",
			foundCols = foundCols || ", " || ":Name(\!"" || (Column( dt, colList[i] ) << get name) || " Pass/Fail\!")"
		);
	);
);

// Create the Row Pass/Fail
Eval( Parse( "dt << New Column( \!"Row Pass/Fail\!", formula( If( Min(" || foundCols || " ) == 1, 1, 0 ) )" ) );

Jim
AT
AT
Level V

Re: how to calculate yield for many columns with embedded spec limits

Thanks Jim. This is exactly what I wanted.

 

I ran the script and found this error. A column is created with title "Row Pass/Fail" and it is all zero.

 

Unexpected end of input. Perhaps there is a missing "," or ")".

Trying to parse arguments of function "New Column".

Line 1 Column 3272: ...s/Fail") ) == 1, 1, 0 ) )►...

 

Resolution Problem with Formula for Column Wafer ID in lot ID:

Column( "Row Pass/Fail" )

 

Thanks for your continuous support.

txnelson
Super User

Re: how to calculate yield for many columns with embedded spec limits

My error, an ")" was left out of the last statement.  It should be:

Eval( Parse( "dt << New Column( \!"Row Pass/Fail\!", formula( If( Min(" || foundCols || " ) == 1, 1, 0 ) ))" ) );
Jim
AT
AT
Level V

Re: how to calculate yield for many columns with embedded spec limits

Thanks Jim. It works now.

MarkDayton
Level IV

Re: how to calculate yield for many columns with embedded spec limits

Why this functionality isn't built in to JMP I don't understand, but how could this script be changed so the pass/fail columns will be dynamic? I would like to be able to adjust the specs to determine effect on yield. The way it is now I would have to delete the added columns each time I wanted to reevaluate the yield.

txnelson
Super User

Re: how to calculate yield for many columns with embedded spec limits

The definition of Spec Limits, typically does not contain their dynamic calculation.  They are set based on design limits, etc.  That aside, regarding your question, do you invision setting the limits dynamically for all columns(parameters) at the same time?  That is, will the limits be set the same for each parameter?  Or would you set each individually?  Using a Data Filter in conjuction with column formulas could handle your request.

Jim
MarkDayton
Level IV

Re: how to calculate yield for many columns with embedded spec limits

What I would like to be able to do is do what if analysis where I can change a couple specs, re-screen the data, and come out with a yield number.
MarkDayton
Level IV

Re: how to calculate yield for many columns with embedded spec limits

Additional detail, I have 75-150 parameters and very few of them have the same limits. In a recent experience, I have three parameters driving yield, and a limited amount of spec relief that I can expect to receive. I need to know which combination of spec changes will yield the biggest improvement, while minimizing the magnitude of the changes.

txnelson
Super User

Re: how to calculate yield for many columns with embedded spec limits

Below is a script that is a very basic, but a good starting point for the development of an interactive yield calculator.  Your requirement is a very neat idea.  Maybe you can develop and add to the File Exchange a new addin, or maybe someone else will do such.  But, here is my starting point script:

Names Default To Here( 1 );

// Create a sample data table
dt = New Table( "Yield",
	Add Rows( 40 ),
	New Column( "Parm 1",
		Numeric,
		"Continuous",
		Format( "Fixed Dec", 5, 0 ),
		Set Property( "Spec Limits", {LSL( 57 ), USL( 67 ), Show Limits( 0 )} ),
		Set Values(
			[59, 61, 55, 66, 52, 60, 61, 51, 60, 61, 56, 65, 63, 58, 59, 61, 62, 65, 63, 62, 63, 64, 65, 64, 68, 64, 69, 62, 64, 67, 65, 66,
			62, 66, 65, 60, 68, 62, 68, 70]
		)
	),
	New Column( "Parm 2",
		Numeric,
		"Continuous",
		Format( "Fixed Dec", 5, 0 ),
		Set Property( "Spec Limits", {LSL( 80 ), USL( 140 ), Show Limits( 0 )} ),
		Set Values(
			[95, 123, 74, 145, 64, 84, 128, 79, 112, 107, 67, 98, 105, 95, 79, 81, 91, 142, 84, 85, 93, 99, 119, 92, 112, 99, 113, 92, 112,
			128, 111, 105, 104, 106, 112, 115, 128, 116, 134, 172]
		)
	),
	New Column( "Parm 1 Pass/Fail",
		Numeric,
		"Continuous",
		Format( "Best", 12 ),
		Value Labels( {0 = "Fail", 1 = "Pass"} ),
		Use Value Labels( 1 ),
		Set Values(
			[1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0]
		)
	),
	New Column( "Parm 2 Pass/Fail",
		Numeric,
		"Continuous",
		Format( "Best", 12 ),
		Value Labels( {0 = "Fail", 1 = "Pass"} ),
		Use Value Labels( 1 ),
		Set Values(
			[1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
		)
	)
);

// A function to set the Pass/Fail columns based upon the current Spec Limits
setPassFail = Function( {Parm},
	USL = (Column( dt, parm ) << get property( "Spec Limits" ))["USL"];
	LSL = (Column( dt, parm ) << get property( "Spec Limits" ))["LSL"];
	Column( dt, parm || " Pass/Fail" )[dt << get rows where( As Column( dt, parm ) >= LSL & As Column( dt, parm ) <= USL )] = 1;
	Column( dt, parm || " Pass/Fail" )[dt << get rows where( As Column( dt, parm ) < LSL | As Column( dt, parm ) > USL )] = 0;
);

//Calculate  the yield for all Pass/Fail columns
calculateYield = Function( {},
	overallYield = 0;
	numberOfRowsThatPassed = 0;
	numberOfRowsThatFailed = 0;

	For( i = 1, i <= N Rows( dt ), i++,
		If( Sum( :Name( "Parm 1 Pass/Fail" )[i], :Name( "Parm 2 Pass/Fail" )[i] ) == N Items( colNamesList ),
			numberOfRowsThatPassed++,
			numberOfRowsThatFailed
			++)
	);

	overallYield = numberOfRowsThatPassed / (numberOfRowsThatPassed + numberOfRowsThatFailed);
);

// Display the Yield Changing Window
nw = New Window( "Interactive Yield Calculation",
	Lineup Box( N Col( 2 ),
		V List Box(
			Text Box( "Parm 1" ),
			p1Upper = Col Maximum( :Name( "Parm 1" ) );
			p1Lower = Col Minimum( :Name( "Parm 1" ) );
			p1 = Range Slider Box(
				Col Mean( :Name( "Parm 1" ) ) - 6 * Col Std Dev( :Name( "Parm 1" ) ),
				Col Mean( :Name( "Parm 1" ) ) + 6 * Col Std Dev( :Name( "Parm 1" ) ),
				p1Lower,
				p1Upper,
				Eval(
					Substitute(
							Expr(
								:Name( "Parm 1" ) << set property( "Spec Limits", {LSL( _LSL_ ), USL( _USL_ ), Show Limits( 0 )} )
							),
						Expr( _LSL_ ), p1Lower,
						Expr( _USL_ ), p1Upper
					)
				);
				returned = setPassFail( "Parm 1" );
				cYield = calculateYield();
				yieldVal << set( cYield );
			);,
			Text Box( "Parm 2" ),
			p2Upper = Col Maximum( :Name( "Parm 2" ) );
			p2Lower = Col Minimum( :Name( "Parm 2" ) );
			p2 = Range Slider Box(
				Col Mean( :Name( "Parm 2" ) ) - 6 * Col Std Dev( :Name( "Parm 2" ) ),
				Col Mean( :Name( "Parm 2" ) ) + 6 * Col Std Dev( :Name( "Parm 2" ) ),
				p2Lower,
				p2Upper,
				Eval(
					Substitute(
							Expr(
								:Name( "Parm 2" ) << set property( "Spec Limits", {LSL( _LSL_ ), USL( _USL_ ), Show Limits( 0 )} )
							),
						Expr( _LSL_ ), p2Lower,
						Expr( _USL_ ), p2Upper
					)
				);
				returned = setPassFail( "Parm 2" );
				cYield = calculateYield();
				yieldVal << set( cYield );
			);,

		),
		V List Box( Text Box( "Yield" ), yieldVal = Number Edit Box() )
	),
	cYield = calculateYield();
	yieldVal << set( cYield );
);
Jim