Loop x,y posizioni nel tempoCiao,
Sono abbastanza nuovo di jmp (attualmente utilizzo jmp 16) e ho una domanda sul seguente scenario. Ho un file CSV che ha le seguenti colonne per ogni imperfezione:
- Timestamp, ID seriale, posizione x, posizione y, dimensione dell'imperfezione (in mm)
Lavoro con un processo di pulizia e lo strumento di ispezione fornisce informazioni per ogni singola imperfezione della giornata. Ci sono un paio di cose che devo monitorare:
1) numero di volte che un particolare ID seriale è stato elaborato e scoprire se è la prima volta che è stato pulito, o la seconda, la terza, ecc.
2) se l'ID seriale è stato pulito più di una volta, devo sapere se una delle combinazioni delle posizioni (x,y) è ancora nello stesso punto dopo ogni pulizia
Rappresentando graficamente le posizioni x e y e quindi filtrando in base al tempo, potrei arrivare a rispondere 2) ma è un passaggio molto manuale. Spero di trovare una soluzione utilizzando jsl che possa automatizzare le informazioni di cui ho bisogno per tracciare.
finestreRe: Loop x,y posizioni nel tempoChe tipo di risoluzione hanno le posizioni x,y? Ad esempio, potrebbero essere sempre numeri interi da 1 a 100, oppure potrebbero essere valori in virgola mobile da 0 a 100 arrotondati allo .01 più vicino oppure potrebbero essere float senza alcun limite apparente alla risoluzione. Quanto dovrebbe essere vicina la coppia x,y per essere una ripetizione? La dimensione dell'imperfezione ha qualcosa a che fare con la sovrapposizione x,y? Oppure la dimensione è sempre inferiore alla griglia x,y e viene ignorata?
Se ci sono solo 100 valori x e 100 y, e se la dimensione non è interessante, allora combinerei i valori x e y in un'unica chiave, x*100+y forse, questo potrebbe rendere più facile testare le ripetizioni . Forse lo stesso per i float arrotondati, fino a circa 6 cifre significative.
Ma se le dimensioni contano, o le distanze devono essere testate, potrei usare un KDTable.
Inoltre, quante righe? meno di qualche migliaio probabilmente non avrà bisogno di particolari ottimizzazioni. Più di un milione probabilmente avrà bisogno di un algoritmo ben congegnato. (Con meno di mille righe, ogni riga può pensare a ogni altra riga e ci sono solo 1.000.000 di confronti, ma raddoppia la dimensione e i confronti quadruplicano.)
Re: Loop x,y posizioni nel tempoCiao @SEG
1: prova a utilizzare la piattaforma di riepilogo Tabella <<. lì, inserisci l'ID seriale, la posizione x e la posizione y nel gruppo.
questo ti darà una riga separata per ogni combinazione unica dei tre.
sarebbe utile rappresentare graficamente questa nuova tabella di riepilogo, basta usare la colonna N come colore o dimensione
2: una volta prodotto un grafico, sotto il triangolo rosso in alto a sinistra puoi scegliere di salvare lo script nella tabella dati o nella finestra dello script. jmp ha appena scritto lo script per te.
se stai usando jmp 16 fai clic su visualizza >> log e otterrai uno script di tutto ciò che hai fatto nella sessione corrente.
facci sapere se aiuta.
ron
Re: Loop x,y posizioni nel tempoCiao,
Potresti aiutarci a capire meglio la tua struttura dei dati condividendo un esempio (i dati fittizi funzionerebbero bene)? In base alla tua descrizione, suppongo che ogni evento di pulizia sia identificabile da una combinazione univoca di timestamp e ID seriale. Inoltre, i tuoi dati includono informazioni replicate (ad es. righe con una combinazione identica di timestamp e ID seriale? Se lo fa, renderà il processo più impegnativo. Infine, dopo aver identificato più eventi di pulizia per un ID seriale, sei interessato a catturare solo se le posizioni sono identiche in tutti gli eventi, identiche tra due eventi qualsiasi o qualcos'altro?
Migliore,
TS
Re: Loop x,y posizioni nel tempo
Ciao Craig
La posizione x e y esce di 3 cifre dopo la virgola. Finché si trovano entro il 3% della stessa posizione, sarebbe considerata un'imperfezione ripetuta. La dimensione non ha nulla a che fare con la sovrapposizione. Ciò che è stato fatto in passato è che una volta che è stato rappresentato graficamente, i primi loop vengono designati come un cerchio in un colore e i secondi loop ottengono una "x" in un altro colore. Una volta che si sovrappongono, è visivamente facile vedere se si trova nella stessa posizione.
In termini di righe potrebbe arrivare a diverse migliaia a seconda di quanto viene eseguito in un giorno. non è mai arrivato a milioni, anche se è una possibilità se guardiamo a un periodo molto lungo alla volta.
Re: Loop x,y posizioni nel tempoCiao Thierry,
Ho allegato uno screenshot dei dati fittizi. come puoi vedere, ogni ID riceverà più risultati contemporaneamente poiché tutte le imperfezioni vengono scritte contemporaneamente, la differenza principale sarebbe la posizione x, y e la dimensione. Si noti inoltre che questo esempio riguarda solo la prima pulizia. La seconda volta, lo stesso ID potrebbe apparire con più o meno righe ed è allora che vorrei scoprire se si ripete e anche essere in grado di identificare che si tratta di un secondo, terzo, ecc.
Dopo più pulizie per un numero di serie, vorrei catturare se le posizioni sono identiche in tutti gli eventi
Re: Loop x,y posizioni nel tempoEcco un po' di codice di avviamento. Dovrai studiarlo per assicurarti che faccia quello che ti aspetti. L'output è nella finestra Log. (Allego un file. Il codice sotto potrebbe essere incasinato perché il sito web ha rimosso alcuni "html non validi". )
// 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 ) ) ) )
);