Subscribe Bookmark RSS Feed

Forcing Full Map with Partial Dataset

CS13

Occasional Contributor

Joined:

Jan 5, 2017

Hi,

 

I'm hoping someone can help with some guidance here.  As part of a larger report generation, I am generating wafer heat maps with the following script:

 

Graph1 = dt << Graph Builder(

   Size( 300, 300 ),

   Show Control Panel( 0 ),

   Show Footer( 0 ),

   Y Group Edge( "Left" ),

   Variables(

          Group X( :Col, Show Title( 0 ) ),

          Group X( :ChipCol, Show Title(0) ),

          Group Y( :Row, Show Title( 0 ) ),

          Group Y( :ChipRow, Show Title(0) ),

          Color( :test_value )

    ),

   Where( (:ReportLevel == Report_Level & :lot == this_lot & :wafer == this_wafer) ),

   By( :VarDescription ),

   Elements( Heatmap( Legend( 13 ) ) ),

   SendToReport(

          Dispatch( {}, "graph title", TextEditBox, {Set Text( "" )} ),

          Dispatch( {}, "X title", TextEditBox, {Set Wrap( 2 )} ),

          Dispatch( {}, "Y title", TextEditBox, {Set Wrap( 2 )} )

    )

)

 

I have up to 150 possible values for :VarDescription and found that running this in a loop to create each individual map, append the journal, and close the map was very clunky.  I found that allowing graph builder to create all the maps at once with the By(:VarDescription) statement was much more fluid, and to build my journal, I can grab the individual maps out of the array positions in the graph object.  What has got me in a bind is that getting a full map is predicated on having values for ALL sites, otherwise I get partial, consolidated maps.  Even if I've only tested a few sites, I want the entire map displayed for spatial consideration.  In my data table, I am including a handful of reference (dummy) rows that represent blank values for all locations in the first column and the first row.  This effectively will force the display of the full map in graph builder when the "dummy" rows are included.  Where I'm stuck is how to include these reference rows for each map when using the By(:VarDescription) statement in graph builder vs using a filter (Where) statement.  I don't think there's a way to do that upon initial creation of the maps.  Is there a way to append data to a graph object after the fact?  Or modify the generated filtering?  I've noticed that the individual maps in the journal end up with modified filters, I assume generated by the By( ) statement.  As an alternative work around that fits into this approach, I've considered just making "dummy" rows for all :VarDescription possibilities but the data table would get awfully large and cluttered.  I'm trying to avoid that.

 

Thanks!

 

1 ACCEPTED SOLUTION

Accepted Solutions
txnelson

Super User

Joined:

Jun 22, 2012

Solution

Here is a script that I believe will give you what you want.  It will generate all of the wafermaps in a journal window.  I left out the Where() clause from your Graph Builder script, because I didn't have the values available, but you should be able to add the line in with no real issues.

Names Default To Here( 1 );
dt = Current Data Table();

// Create the empty wafer map data set
dtWaferMap = dt << Summary(
	private,
	Group( :Col, :ChipCol, :Row, :ChipRow ),
	Freq( "None" ),
	Weight( "None" )
);
dtWaferMap << delete columns( "N Rows" );

// Get a list of all of the VarDescriptions
Current Data Table( dt );
Summarize( dt, byVarDes = by( :VarDescription ) );

// Create the output journal
NW = New Window( "Heat Maps", <<journal, TheVLB = V List Box() );

// Loop through all of the VarDescription values and create the wafer maps
For( i = 1, i <= N Items( byVarDes ), i++, 
	// Create a copy of the blank wafer map data set
	dtDisplay = dtWaferMap << subset( invisible, selected columns( 0 ), selected rows( 0 ) );
	
	// Subset the data table for the current level of of the VarDescription
	dt << select where( :VarDescription == byVarDes[i] );
	dtData = dt << subset( invisible, selected Rows( 1 ), selected columns( 0 ) );
	
	// Bring together the dummy wafer map and the subsetted data
	dtDisplay << Update(
		With( dtData ),
		Match Columns( :Col = :Col, :ChipCol = :ChipCol, :Row = :Row, :ChipRow = :ChipRow )
	);
	
	// Set all values of VarDescription to the current byVarDis value
	dtDisplay:VarDescription << set each value( Eval( byVarDes[i] ) );
		
	// Create the graphical output
	gb = dtDisplay << Graph Builder(
		invisible,
		Size( 300, 300 ),
		Show Control Panel( 0 ),
		Show Footer( 0 ),
		Y Group Edge( "Left" ),
		Variables(
			Group X( :Col, Order By( :ChipCol, Ascending, Order Statistic( "Mean" ) ), Show Title( 0 ) ),
			Group X( :ChipCol, Show Title( 0 ) ),
			Group Y( :Row, Show Title( 0 ) ),
			Group Y( :ChipRow, Show Title( 0 ) ),
			Color( :test_value )
		),
		By( :VarDescription ),
		Elements( Heatmap( Legend( 33 ) ) ),
		SendToReport(
			Dispatch( {}, "graph title", TextEditBox, {Set Text( "" )} ),
			Dispatch( {}, "X title", TextEditBox, {Set Wrap( 2 )} ),
			Dispatch( {}, "Y title", TextEditBox, {Set Wrap( 2 )} )
		)
	);

	// Add the display to the output window
	TheVLB << append( Report( gb )[Outline Box( 1 )] );
	 
	// Close the display and unneeded data tables
	gb << close window;
	Close( dtDisplay, nosave );
	Close( dtData, nosave );
);

Close( dtWaferMap, nosave );

using page.PNG

Jim
7 REPLIES
txnelson

Super User

Joined:

Jun 22, 2012

I am attempting to replicate your issue.

A couple of questions:

Could you insert a screen shot of your results?

What are the definitions of Row and ChipRow and of Col and ChipCol?

Have you explored using a Shape Map?

Jim
CS13

Occasional Contributor

Joined:

Jan 5, 2017

 

Row and Col basically define the map grid.  ChipRow and ChipCol are essentially sub-row and sub-column.

This is an example output which is generated for each unique :VarDescription.  This is how it appears when there is data for all sites.

 

Untitled.png

What I'm trying to do is to force it to look complete, even with partial data.  The dummy rows accomplish this and I get this.

 

Untitled2.png

Without the benefit of the dummy rows, this is what it would look like...

 

Untitled3.png

 

 

I haven't explored a shape map, but with a little upfront work, that might be the better way to go.  I can look into it a little more. 

 

CS13

Occasional Contributor

Joined:

Jan 5, 2017

Just as a follow up, I looked a little more into shape maps.  It looks like it might work in some fashion, but I don't see how to easily adopt the row/col, subrow/subcol format of my plots which has importance for our application.  I suppose I could brute force it.  The maps I'm generating are not used simply as a final product spatial representation on x/y coordinates.  They are used for addressing parts and quickly communicating to other people.  Dealing in x/y would just add another layer of translation which is a bit clunky for our purposes.

txnelson

Super User

Joined:

Jun 22, 2012

I made up some sample data using your data structure, and created a replica of your heat map. I then added a second VarDescription set of values, with only a subset of the cells.  Then, rather than using a "BY" I dropped the VarDescription on to the Page area and got the following

using page.PNG

The issue with the Page, is that it only allows for 100 page values.  However, this is easily overcome by subsetting your data into 100 page sample.

Here is the code generated by Graph Builder

Graph Builder(
	Size( 418, 646 ),
	Show Control Panel( 0 ),
	Show Footer( 0 ),
	Y Group Edge( "Left" ),
	Variables(
		Page( :VarDescription ),
		Group X( :Col, Show Title( 0 ) ),
		Group X( :ChipCol, Show Title( 0 ) ),
		Group Y( :Row, Show Title( 0 ) ),
		Group Y( :ChipRow, Show Title( 0 ) ),
		Color( :test_value )
	),
	Elements( Heatmap( Legend( 33 ) ) ),
	SendToReport( Dispatch( {}, "graph title", TextEditBox, {Set Text( "" )} ) )
);

 

Jim
CS13

Occasional Contributor

Joined:

Jan 5, 2017

I had actually started with Page( ) way back, but the problem is that it only works if all the maps describe subsets of the same parameter since there is a common legend/scale.  I really need each map to be a different parameter, and By( ) actually creates discrete plots.

txnelson

Super User

Joined:

Jun 22, 2012

Solution

Here is a script that I believe will give you what you want.  It will generate all of the wafermaps in a journal window.  I left out the Where() clause from your Graph Builder script, because I didn't have the values available, but you should be able to add the line in with no real issues.

Names Default To Here( 1 );
dt = Current Data Table();

// Create the empty wafer map data set
dtWaferMap = dt << Summary(
	private,
	Group( :Col, :ChipCol, :Row, :ChipRow ),
	Freq( "None" ),
	Weight( "None" )
);
dtWaferMap << delete columns( "N Rows" );

// Get a list of all of the VarDescriptions
Current Data Table( dt );
Summarize( dt, byVarDes = by( :VarDescription ) );

// Create the output journal
NW = New Window( "Heat Maps", <<journal, TheVLB = V List Box() );

// Loop through all of the VarDescription values and create the wafer maps
For( i = 1, i <= N Items( byVarDes ), i++, 
	// Create a copy of the blank wafer map data set
	dtDisplay = dtWaferMap << subset( invisible, selected columns( 0 ), selected rows( 0 ) );
	
	// Subset the data table for the current level of of the VarDescription
	dt << select where( :VarDescription == byVarDes[i] );
	dtData = dt << subset( invisible, selected Rows( 1 ), selected columns( 0 ) );
	
	// Bring together the dummy wafer map and the subsetted data
	dtDisplay << Update(
		With( dtData ),
		Match Columns( :Col = :Col, :ChipCol = :ChipCol, :Row = :Row, :ChipRow = :ChipRow )
	);
	
	// Set all values of VarDescription to the current byVarDis value
	dtDisplay:VarDescription << set each value( Eval( byVarDes[i] ) );
		
	// Create the graphical output
	gb = dtDisplay << Graph Builder(
		invisible,
		Size( 300, 300 ),
		Show Control Panel( 0 ),
		Show Footer( 0 ),
		Y Group Edge( "Left" ),
		Variables(
			Group X( :Col, Order By( :ChipCol, Ascending, Order Statistic( "Mean" ) ), Show Title( 0 ) ),
			Group X( :ChipCol, Show Title( 0 ) ),
			Group Y( :Row, Show Title( 0 ) ),
			Group Y( :ChipRow, Show Title( 0 ) ),
			Color( :test_value )
		),
		By( :VarDescription ),
		Elements( Heatmap( Legend( 33 ) ) ),
		SendToReport(
			Dispatch( {}, "graph title", TextEditBox, {Set Text( "" )} ),
			Dispatch( {}, "X title", TextEditBox, {Set Wrap( 2 )} ),
			Dispatch( {}, "Y title", TextEditBox, {Set Wrap( 2 )} )
		)
	);

	// Add the display to the output window
	TheVLB << append( Report( gb )[Outline Box( 1 )] );
	 
	// Close the display and unneeded data tables
	gb << close window;
	Close( dtDisplay, nosave );
	Close( dtData, nosave );
);

Close( dtWaferMap, nosave );

using page.PNG

Jim
CS13

Occasional Contributor

Joined:

Jan 5, 2017

Jim - Thanks!  This is an excellent approach.  I've been learning JMP on the fly and I think part of what made a looped approach for each plot so clunky early on was my inexperience with generating graphs and tables invisibly for manipulation and closing them out behind the scenes.  I do like the idea of creating a template in this manner and just filling in data wherever it exists.  I will probably need to overhaul a good chunk of my script as there is a lot of different processing I'm doing, but it will be for the better in the long run.  Thanks again!

 

Cory