Looping x,y locations over timeHello,
I'm fairly new to jmp (currently using jmp 16) and have a question about the following scenario. I have a csv file that has the following columns for each imperfection:
- Timestamp, serial ID, x location, y location, size of imperfection (in mm)
I work with a cleaning process and the inspection tool gives information for every single imperfection in the day. There are a couple of things I need to track:
1) number of times a particular serial ID has been processed and finding out if its the first time it has been cleaned, or second, third, etc.
2) if the serial ID has been cleaned more than once, then I need to know if any of combination of the (x,y) locations is still in the same spot after each cleaning
Graphing the x and y locations and then filtering by time I could get to answer 2) but its a very manual step. I am hoping to find a solution using jsl that could automate the information that I need to track.
WindowsRe: Looping x,y locations over timeHi @SEG
1: try using the Table << summary platform. there, just put serial ID, x location and y location in the group.
this will give you a separate row for each unique combination of the three.
graphing this new summary table would be useful, just use the N column as color or size
2: once you produce a graph once, under the red triangle in top left you can choose to save the script to the data table or script window. jmp just wrote the script for you.
if you are using jmp 16 click view>>log and you will get a script of all you did in the current session.
let us know if it helps.
ron
Re: Looping x,y locations over timeHi,
Could you help us better understand your data structure by sharing an example (mock data would work fine)? Based on your description, I surmise that each cleaning event is identifiable by a unique combination of Timestamp and serial ID. Also, does your data include any replicate information (i.e., rows with an identical combination of Timestamp and serial ID? If it does, it will make the process more demanding. Finally, after identifying multiple cleaning events for a serial ID, are you interested in only capturing if the locations are identical across all events, identical between any two events, or something else?
Best,
TS
Re: Looping x,y locations over time
Hello Craig
The x and y location go out 3 digits after the decimal point. As long as they are in within 3% of the same location it would be considered a repeat imperfection. The size does not have anything to do with the overlap. What has been done in the past is once its graphed the first loops get designated as a circle in one color and the second loops get an "x" in another color. Once they overlap its visually easy to see if its in the same location.
In terms of rows it could get into the several thousands depending on how much is ran on a day. its never crossed into millions although it a possibility if we look over a very long period at a time.
Re: Looping x,y locations over timeHello Thierry,
I attached a screenshot of the mock data. as you can see, each ID will get multiple hits at the same time stamp as all the imperfections get written at the same time, the main difference would be the x,y location and the size. Also note that this example is only of a first time cleaning. The second time, the same ID could appear with more or less rows and thats when I'd like to find if its repeating and also be able to identify that its a second, third, etc loops of cleaning.
After multiple cleanings for a serial numeber, I'd like to capture if the locations are identical across all events
Re: Looping x,y locations over timeHere's some starter code. You'll need to study it to make sure it does what you expect. The output is in the Log window. (I'll attach a file. the code below might be messed up because the web site removed some "invalid html". )
// synthesize some data
radius = 1;
dt = New Table( "Untitled",
Add Rows( 1000 ), // <<<<<<<<<<<<<< change number of rows here
New Column( "time", Numeric, "Continuous", Format( "Best", 12 ) ),
New Column( "waferID", Numeric, "Continuous", Format( "Best", 12 ) ),
New Column( "xLocation", Numeric, "Continuous", Format( "Best", 12 ) ),
New Column( "yLocation", Numeric, "Continuous", Format( "Best", 12 ) )
);
here:time = 0; // for this synth data, time just increments by 1
here:waferID = 0; // and the waferID is random 0-9
For( row = 1, row <= N Rows( dt ), row += 1,
If( Random Uniform() > .8, // determines how many points in a cleaning, before time changes and wafer re-randomizes
here:time += 1;
here:waferID = Random Integer( 0, 9 );
);
dt:time[row] = here:time;
dt:waferID[row] = here:waferID;
dt:xLocation[row] = Round( Random Uniform( -radius, radius ), 2 );
dt:yLocation[row] = Round( Random Uniform( -radius, radius ), 2 );
);
// find the unique waferIDs using summary
dtWafer = dt << Summary( Group( :waferID ), Link to original data table( 1 ) );
dtWaferTime = dt << Summary( Group( :waferID, :time ) );
dtNWafer = dtWaferTime << Summary( Group( :waferID ) ); //number of distinct times for this wafer is number of cleanings
close = .03; // <<< this determines how close makes a hit
// produce a report for each waferID that shows up in the cleaning data...
For( iWafer = 1, iWafer <= N Rows( dtWafer ), iWafer += 1,
dtWafer << clear select << selectrows( iWafer ); // dtWafer selection also selects rows in dt because linked
rows = dt << get selected rows; // all the rows for this wafer, across all times
// rows is a 1-column matrix of row numbers in dt for this wafer. the argument to KDTable
// is all the locations over all cleanings for this wafer.
kdt = KDTable( dt[rows, {xLocation, yLocation}] );
// report header for each waferID... the report might have no lines below the header, or a bunch... Not indented.
Write( Eval Insert( "\!n\!nprocessing waferID=^dtWafer:waferID[iWafer]^, ^nrows(rows)^ points during ^dtNWafer:nrows[iWafer]^ cleanings" ) );
For( irow = 1, irow <= N Rows( rows ), irow += 1, // the rows should be ascending time
row = rows[irow]; // row (singular) is an index to dt
// find rows {up to this many,up to this far} near irow
{index, distance} = kdt << kNearestRows( {dtWafer:NRows[iWafer], close}, irow );
// above, index is into the 1-column matrix of row numbers. below, it becomes index into dt
index = rows[index];
printedHeader = 0; // don't print this header unless there are duplicates to go with it
// distance[] and index[] have same number of rows; index is indexes to near neighbors and distance is to the neighbor
For( idistance = 1, idistance <= N Items( distance ), idistance += 1,
If( dt:waferID[index[idistance]] != dt:waferID[row] | dt:waferID[row] != dtWafer:waferID[iWafer],
Throw( "wafer mismatch" )
);// sanity check
If( distance[idistance] <= close, // typically there is one item with a bigger distance than we care about, must be ignored by else-break below.
If( !printedHeader, // a little indented...
Write(
Eval Insert(
"\!n matches for row ^row^ time ^dt:time[row]^ loc [^char(dt:xLocation[row],7,3)^,^char(dt:yLocation[row],7,3)^]"
)
);
printedHeader = 1;
);
// there can be more than one subsequent cleaning, indented more...
Write( Eval Insert( "\!n row ^index[idistance]^ time ^dt:time[index[idistance]]^ " ) );
Write( Eval Insert( "[^char(dt:xLocation[index[idistance]],7,3)^,^char(dt:yLocation[index[idistance]],7,3)^]) " ) );
Write( Eval Insert( "dist(^distance[idistance]^)" ) );
, //else
Break()
);
);
kdt << removerows( irow ); // never look back at this row from future rows
);
);
// a graph to examine the rows found to be close.
dt << Graph Builder(
Size( 867, 787 ),
Show Control Panel( 0 ),
Variables( X( :xLocation ), Y( :yLocation ) ),
Elements( Points( X, Y, Legend( 5 ) ) ),
Local Data Filter( Add Filter( columns( :waferID ), Modeling Type( :waferID, Nominal ), Display( :waferID, N Items( 14 ) ) ) )
);