Schleifen von XY-Positionen im Laufe der ZeitHallo,
Ich bin ziemlich neu bei jmp (derzeit verwende ich jmp 16) und habe eine Frage zu folgendem Szenario. Ich habe eine CSV-Datei mit den folgenden Spalten für jede Unvollkommenheit:
- Zeitstempel, Seriennummer, x-Ort, y-Ort, Größe der Unvollkommenheit (in mm)
Ich arbeite mit einem Reinigungsprozess und das Inspektionstool gibt Auskunft über jede einzelne Unvollkommenheit des Tages. Es gibt ein paar Dinge, die ich verfolgen muss:
1) wie oft eine bestimmte Seriennummer verarbeitet wurde und herauszufinden, ob es das erste Mal ist, dass sie gereinigt wurde, oder das zweite, dritte usw.
2) Wenn die Seriennummer mehr als einmal gereinigt wurde, muss ich wissen, ob sich eine der Kombinationen der (x,y)-Positionen nach jeder Reinigung immer noch an derselben Stelle befindet
Die x- und y-Positionen grafisch darzustellen und dann nach Zeit zu filtern, könnte ich zu Antwort 2) bringen, aber es ist ein sehr manueller Schritt. Ich hoffe, mit jsl eine Lösung zu finden, die die Informationen automatisieren kann, die ich nachverfolgen muss.
WindowsBetreff: Schleifen von x,y-Positionen im Laufe der Zeit@Craige_Hales Ich werde definitiv KDTable() << kNearestRows( ) zu meiner Toolbox hinzufügen. Ich wusste nicht, dass das existiert und bin so froh zu erfahren, dass es so ist.
Betreff: Schleifen von x,y-Positionen im Laufe der Zeit@ngambles Wow! Ich sollte tabulate und dt<@DonMcCormack
Betreff: Schleifen von x,y-Positionen im Laufe der Zeit
ich mag Craige_Hales Lösung, aber ich möchte auch meine Lösung bereitstellen, da ich in der Vergangenheit vor ähnlichen Aufgaben stand.
Mein Ansatz bestand darin, die verfügbaren Daten zu verwenden, um zusätzliche Informationen zu berechnen, diese der Datentabelle hinzuzufügen, und dann war ich in der Lage, Berichte zu erstellen (Graph Builder, tabellarisieren usw.), die die endgültigen Ergebnisse zeigten.
In Ihrer Anfrage möchten Sie berechnen können, wie oft eine bestimmte Seriennummer verarbeitet wurde.Ich fand es auch sehr nützlich, eine Indikatorspalte zu erstellen, die Dateneinträge von der letzten/endgültigen Verarbeitung eines Wafers identifiziert.
Basierend auf den Beispieldaten aus "mock data.PNG" würde ich Folgendes tun:
- Berechnen Sie die fortlaufende Nummer für jedes Mal, wenn ein Wafer verarbeitet wurde
- Berechnen Sie die letzte Zeit, zu der jeder Wafer verarbeitet wurde
- Identifizieren von defekten Orten anhand des Namens basierend auf ungefähren Orten
- Berechnen Sie, wie oft jeder Standortname für jeden Wafer identifiziert wurde
Um dies zu erreichen, generiere ich mehrere temporäre Datentabellen mit tabulate, füge einige Formeln hinzu, um die gewünschten Antworten zu erhalten, und füge sie dann wieder in die ursprüngliche Datentabelle ein.
Der JSL-Code würde in etwa so aussehen
names default to here(1);
/////////// make example data table /////////////////////
dt = New Table( "example data set",
Add Rows( 13 ),
New Column( "Time",
Numeric,
"Nominal",
Format( "Best", 12 ),
Set Values( [1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4] )
),
New Column( "WaferID",
Numeric,
"Nominal",
Format( "Best", 12 ),
Set Values( [1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 1, 1, 1] )
),
New Column( "X location",
Numeric,
continuous,
Format( "Best", 12 ),
Set Values(
[2.745, 1.566, -28.143, -4.793, -29.251, 19.527, 6.581, 29.37, 4.907,
21.699, 2.745, -4.793, 6.581]
)
),
New Column( "Y location",
Numeric,
continuous,
Format( "Best", 12 ),
Set Values(
[44.164, 61.915, -42.954, -38.091, -46.659, 32.201, -24.715, 41.533,
60.217, -60.26, 44.164, -38.091, -24.715]
)
),
New Column( "Size",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values(
[0.164, 0.136, 0.125, 0.122, 0.122, 0.036, 0.035, 0.035, 0.035, 0.034,
0.164, 0.122, 0.035]
)
)
);
//dt = current data table();
/////////// create temporary data table to determine Clean Count and Final Clean /////////////////
tab = dt << Tabulate(
Show Control Panel( 0 ),
Full Path Column Name( 1 ),
Add Table( Row Table( Grouping Columns( :WaferID, :Time ) ) )
);
dtx = tab << make into data table();
tab << close window();
dtx << New Column("Wafer Clean Count", Numeric, "Nominal", Formula(Col Rank(:Time, :WaferID)));
dtx << New Column("Final Wafer Clean", Numeric, "Nominal", Formula(If(:Time == Col Maximum(:Time, :WaferID), 1, 0)));
dtx << delete Column("N");
///////// move Clean Count and Final Clean information back to original data table //////////////
dt << Update(
With( dtx ),
Match Columns( :WaferID = :WaferID, :Time = :Time ),
Add Columns from Update Table( :Wafer Clean Count, :Final Wafer Clean ),
Replace Columns in Main Table( :Wafer Clean Count, :Final Wafer Clean )
);
//////// close data table //////////////////////////////////////////////////////
close(dtx, no save);
//////// modify X & Y values to allow variation in measurements////////////////
dt << new column("X_Temp", numeric, continuous, formula(round(:X location, 1)));
dt << new column("Y_Temp", numeric, continuous, formula(round(:Y location, 1)));
/////// create temporary data table to name defect locations ///////////////
tab = dt << Tabulate(
Show Control Panel( 0 ),
Include missing for grouping columns( 1 ),
Full Path Column Name( 1 ),
Add Table( Row Table( Grouping Columns( :X_Temp, :Y_Temp ) ) )
);
dtx = tab << make into data table();
tab << close window();
dtx << new column("Location", character, nominal, formula("L" || char(row())));
dtx << delete column("N");
//////// move Location information back to original data table ////////////////
dt << Update(
With( dtx ),
Match Columns( :X_Temp = :X_Temp, :Y_Temp = :Y_Temp ),
Add Columns from Update Table( :Location ),
Replace Columns in Main Table( :Location )
);
/////// clean up /////////////////////////
close(dtx, no save);
dt << delete columns(
{
"X_Temp",
"Y_Temp"
}
);
/////// calculate the number of times a defect location occured on a given wafer ////////
dt << new column("Wafer Location Count", numeric, nominal, formula(Col Rank( :Time, :Location, :WaferID )));
/////// make some reports /////////////
nw = new window("results",
h list box(
gb = dt << Graph Builder(
Show Control Panel( 0 ),
Variables(
X( :X location ),
Y( :Y location ),
Group X( :Wafer Clean Count ),
Group Y( :WaferID ),
Color( :Wafer Location Count )
),
Elements( Points( X, Y, Legend( 7 ) ) )
),
tab = dt << Tabulate(
Show Control Panel( 0 ),
Include missing for grouping columns( 1 ),
Full Path Column Name( 1 ),
Add Table(
Column Table( Statistics( Max ), Analysis Columns( :Wafer Location Count ) ),
Row Table( Grouping Columns( :WaferID, :X location, :Y location ) )
),
Local Data Filter(
Add Filter(
columns( :Final Wafer Clean ),
Where( :Final Wafer Clean == 1 )
)
)
)
)
);Bei der Benennung der Defektstellen habe ich die x-Koordinate und die y-Koordinate auf eine Dezimalstelle gerundet, um eine gewisse Abweichung in den Positionsmessungen zu ermöglichen. Dies kann für Ihre Anforderungen ausreichend sein oder nicht, aber dieser Ansatz ermöglicht es Ihnen, die Formel für X_Temp und Y_Temp zu ändern, und der Rest funktioniert weiterhin wie erwartet.
Die resultierende Datentabelle enthält die folgenden zusätzlichen Spalten:
- Wafer Clean Count
- enthält die fortlaufende Nummer für die Anzahl der auf dem Wafer durchgeführten Reinigungen
- Endreinigung des Wafers
- Indikatorspalte, die null ist, wenn der Eintrag nicht das letzte Mal war, als der Wafer bearbeitet wurde, und eine Eins, wenn es das letzte Mal war, als der Wafer bearbeitet wurde
- Ort
- ein Name, der der ungefähren Fehlerstelle zugeordnet ist
- Anzahl der Wafer-Standorte
- enthält die aufeinanderfolgende Anzahl von Malen, in denen dieser Defektortname auf einem gegebenen Wafer aufgetreten ist
Mit der resultierenden Datentabelle wäre man in der Lage, die von Ihnen gestellten Fragen und mehr zu beantworten. Einige der möglichen Fragen, die untersucht werden könnten, sind unter anderem:
- welche Schadstellen nach mehreren Reinigungszyklen bestehen geblieben sind
- Wie hoch ist die Gesamtfehlerrate nach dem ersten Wafer-Reinigungszyklus?
- Wie hoch ist die Gesamtfehlerrate, nachdem alle Reinigungszyklen durchgeführt wurden?
- Wie hoch ist die durchschnittliche Anzahl der Reinigungszyklen pro Wafer?
- Gibt es Bereiche, die durchweg defekte Bereiche aufweisen, die gereinigt werden müssen?
Ich hoffe, das hilft.
Betreff: Schleifen von x,y-Positionen im Laufe der ZeitHier ist ein Startcode. Sie müssen es studieren, um sicherzustellen, dass es das tut, was Sie erwarten. Die Ausgabe erfolgt im Log-Fenster. (Ich hänge eine Datei an. Der folgende Code könnte durcheinander geraten sein, weil die Website "ungültiges HTML" entfernt hat). )
// 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 ) ) ) )
);
Betreff: Schleifen von x,y-Positionen im Laufe der ZeitHallo Thierry,
Ich habe einen Screenshot der Scheindaten angehängt. Wie Sie sehen können, erhält jede ID mehrere Treffer zum selben Zeitstempel, da alle Unvollkommenheiten gleichzeitig geschrieben werden. Der Hauptunterschied wäre die x-, y-Position und die Größe. Beachten Sie auch, dass es sich bei diesem Beispiel nur um eine erstmalige Reinigung handelt. Beim zweiten Mal könnte dieselbe ID mit mehr oder weniger Zeilen erscheinen, und dann möchte ich herausfinden, ob sie sich wiederholt, und auch erkennen können, dass es sich um eine zweite, dritte usw. Reinigungsschleife handelt.
Nach mehreren Reinigungen für eine Seriennummer möchte ich festhalten, ob die Orte bei allen Veranstaltungen identisch sind
Betreff: Schleifen von x,y-Positionen im Laufe der Zeit
Hallo Craig
Die x- und y-Position gehen 3 Ziffern nach dem Dezimalpunkt aus. Solange sie sich innerhalb von 3 % der gleichen Stelle befinden, würde dies als wiederholte Unvollkommenheit angesehen werden. Die Größe hat nichts mit der Überlappung zu tun. Was in der Vergangenheit getan wurde, ist, sobald es grafisch dargestellt wird, werden die ersten Schleifen als Kreis in einer Farbe bezeichnet und die zweiten Schleifen erhalten ein "x" in einer anderen Farbe. Sobald sie sich überlappen, ist es visuell leicht zu erkennen, ob es sich an derselben Stelle befindet.
In Bezug auf die Reihen könnte es in die mehrere Tausend gehen, je nachdem, wie viel an einem Tag gelaufen wird. Es hat nie Millionen überschritten, obwohl es eine Möglichkeit ist, wenn wir über einen sehr langen Zeitraum auf einmal schauen.
Betreff: Schleifen von x,y-Positionen im Laufe der ZeitHi,
Könnten Sie uns helfen, Ihre Datenstruktur besser zu verstehen, indem Sie uns ein Beispiel geben (Scheindaten würden gut funktionieren)? Aufgrund Ihrer Beschreibung gehe ich davon aus, dass jeder Reinigungsvorgang durch eine eindeutige Kombination aus Zeitstempel und Seriennummer identifizierbar ist. Enthalten Ihre Daten auch Replikationsinformationen (d. h. Zeilen mit einer identischen Kombination aus Zeitstempel und Seriennummer)? Wenn dies der Fall ist, wird der Prozess anspruchsvoller. Sind Sie schließlich, nachdem Sie mehrere Reinigungsereignisse für eine Seriennummer identifiziert haben, daran interessiert, nur zu erfassen, ob die Orte bei allen Ereignissen identisch sind, bei zwei beliebigen Ereignissen identisch sind oder etwas anderes?
Am besten,
TS
Betreff: Schleifen von x,y-Positionen im Laufe der ZeitHi @SEG
1: Versuchen Sie, die Zusammenfassungsplattform Table << zu verwenden. Geben Sie dort einfach die Seriennummer, den x-Standort und den y-Standort in die Gruppe ein.
Dadurch erhalten Sie eine separate Zeile für jede einzigartige Kombination der drei.
Es wäre nützlich, diese neue Übersichtstabelle grafisch darzustellen. Verwenden Sie einfach die N-Spalte als Farbe oder Größe
2: Sobald Sie einmal ein Diagramm erstellt haben, können Sie unter dem roten Dreieck oben links wählen, ob Sie das Skript in der Datentabelle oder im Skriptfenster speichern möchten. jmp hat gerade das Skript für Sie geschrieben.
Wenn Sie jmp 16 verwenden, klicken Sie auf Ansicht >> Protokoll und Sie erhalten ein Skript mit allem, was Sie in der aktuellen Sitzung getan haben.
lass es uns wissen, wenn es hilft.
Ron
Betreff: Schleifen von x,y-Positionen im Laufe der ZeitWelche Art von Auflösung haben die x,y-Positionen? Sie könnten beispielsweise immer ganze Zahlen von 1 bis 100 sein, oder sie könnten Gleitkommawerte von 0 bis 100 sein, die auf die nächste 0,01 gerundet werden, oder sie könnten Gleitkommazahlen ohne offensichtliche Begrenzung der Auflösung sein. Wie nah müsste das x,y-Paar sein, um eine Wiederholung zu sein? Hat die Größe der Unvollkommenheit etwas mit der x,y-Überlappung zu tun? Oder ist die Größe immer kleiner als das x,y-Raster und wird ignoriert?
Wenn es nur 100 x- und 100 y-Werte gibt und die Größe nicht interessant ist, würde ich die x- und y-Werte zu einem einzigen Schlüssel kombinieren, x*100+y vielleicht, das könnte es einfacher machen, auf Wiederholungen zu testen . Vielleicht dasselbe für gerundete Floats, bis zu etwa 6 signifikanten Stellen.
Aber wenn es auf die Größe ankommt oder die Entfernungen getestet werden müssen, könnte ich einen KDTable verwenden.
Außerdem, wie viele Zeilen? Weniger als ein paar Tausend benötigen wahrscheinlich keine besondere Optimierung. Mehr als eine Million benötigen wahrscheinlich einen gut durchdachten Algorithmus. (Bei weniger als tausend Zeilen kann jede Zeile an jede andere Zeile denken und es gibt nur 1.000.000 Vergleiche, aber die doppelte Größe und der Vergleich vervierfacht sich.)