2012-02-15 10 views
5

Supponiamo di disporre di una serie di dati (un vettore specifico). Posso plottarlo elemento per elemento in sequenza usando Gnuplot in modo tale da sembrare un vero segnale di vita che viene tracciato attraverso un monitor?Tracciare i dati in sequenza da emacs utilizzando Common Lisp e Gnuplot

So che posso scrivere tutti i dati in un file di testo utilizzando Common Lisp, quindi con gnuplot I può essere stampato in un formato batch. Quello di cui ho bisogno è che voglio mettere un punto sulla mia trama mentre i dati arrivano in sequenza.

I dati verranno probabilmente generati all'interno di un ciclo, pertanto è possibile considerare l'asse x come l'asse del tempo discreto con valore intero. Quindi nel ciclo se il primo elemento dell'array è generato come 5, vorrei mettere un punto sul mio grafico su (0,5). Quindi se il secondo elemento è generato come 3, vorrei mettere un altro punto sul mio grafico su (1,7) (preservando il vecchio punto dati). Quindi mentre eseguo l'iterazione del ciclo, tracciamo i dati in sequenza.

Sto usando emacs e Common Lisp per i miei scopi e voglio tracciare questi dati rimanendo all'interno di questi strumenti. Se ci sono altre opzioni oltre a Gnuplot, mi piacerebbe ascoltarle.

Se questo non è facilmente possibile, sarebbe bello, se posso eseguire un file di comando Gnuplot con un comando Common Lisp.

edit:

seguenti avvertenze persone hanno dato in questa discussione, ho scritto un codice utilizzando cgn che utilizza ltk.
In questo momento apro due finestre x11 alle posizioni preimpostate sullo schermo e accedo al ciclo. In loop ogni volta che apro un flusso e scrivo i dati (onde seno e coseno di 0,25 Hz campionati a 20 Hz) nel file di testo trial.txt con l'opzione :if-exists :append e chiudi il flusso. Quindi ad ogni iterazione tracciamo l'intero dato usando gnuplot tramite il comando format-gnuplot. Questo codice mi dà due finestre di intervalli x e y pre-specificati e quindi si possono osservare le evoluzioni delle onde sinusoidali e coseno di cui sopra nelle finestre.
Come ho già detto, non ho un solido background di programmazione (sono un ingegnere elettrico che in qualche modo ha terminato l'uso di una comune lisc) e sono abbastanza sicuro che il mio codice non sia ottimale e poco elegante. Se avete altri consigli, correzioni, ecc. Mi piacerebbe molto sentirli. Il codice è qui:

(setf filename "trial.txt") 
(setf path (make-pathname :name filename)) 
(setf str (open path :direction :output :if-exists :supersede :if-does-not-exist :create)) 
(format str "~,4F ~,4F" -1 -1) 
(close str) 

;start gnuplot process 
(start-gnuplot "/Applications/Gnuplot.app/Contents/Resources/bin/gnuplot") 

;set 2 x11 windows with the following properties 
(format-gnuplot "cd ~S" "Users/yberol/Desktop/lispbox/code") 
(format-gnuplot "set terminal x11 0 position 0,0") 
(format-gnuplot "set xrange [0:10]") 
(format-gnuplot "set yrange [-1:1]") 
(format-gnuplot "unset key") 
(format-gnuplot "set grid") 

(format-gnuplot "plot ~S using 1" filename) 
(format-gnuplot "set terminal x11 1 position 800,0") 
(format-gnuplot "plot ~S using 2" filename) 

;write data into text 
(loop :for i :from 0 :to 10 :by (/ 1 20) :do 
    (setf str (open path :direction :output :if-exists :append :if-does-not-exist :create)) 
    (format str "~,4F ~,4F ~,4F ~%" i (sin (* 2 pi (/ 5 20) i)) (cos (* 2 pi (/ 5 20) i))) 
    (close str) 
    (format-gnuplot "set terminal x11 0") 
    (format-gnuplot "plot ~S using 1:2 with lines" filename) 
    (format-gnuplot "set terminal x11 1") 
    (format-gnuplot "plot ~S using 1:3 with lines" filename) 
    (sleep 0.1)) 
(close-gnuplot) 

Grazie mille.

+0

Così si desidera una finestra vuota, e poi, punto dopo il punto tutti i vostri dati vengono visualizzati con un ritardo tra la visualizzazione punto n e punto n + 1, dì un secondo, sto comprendendo la tua domanda giusto? –

+0

esattamente, 1 secondo oa seconda della frequenza di campionamento dei miei dati Ts sec. – YBE

+0

A meno che non mi sbagli, questo non ha quasi nulla con Emacs, giusto? Per una soluzione alternativa, potresti prendere in considerazione R, come illustrato in questo [thread CV] (http://stats.stackexchange.com/q/6021/930). Se riesco a pensare ad una soluzione adeguata in CL/gnuplot, lo posterò. – chl

risposta

3

cgn è una soluzione Common Lisp che lavora per l'interfacciamento con gnuplot, che utilizza LTK

+0

funzionerà in modo dinamico come ho chiesto nella domanda? Grazie mille in anticipo. – YBE

+0

Sì, sicuramente. Hai solo bisogno di 'start-gnuplot', e quindi puoi valutare interattivamente le diverse funzioni' cgn' –

+0

Ho usato cgn per il tracciamento di ieri. Funziona. Tuttavia non sono sicuro, come posso raggiungere l'obiettivo di tracciare i dati dinamicamente in modo equivalente alla funzione drawnow di MATLAB in gnuplot. Hai qualche idea? Grazie in anticipo. – YBE

1

Non ho esperienza con Gnuplot e una ricerca rapida non ha generato troppe informazioni. Ma forse posso proporre un approccio. Diciamo che il tuo input è un po ', per esempio' (1 2 3 4 5) sarebbe '((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5)), puoi generare un grafico per ciascuno e utilizzare una libreria grafica come lispbuilder-sdl per visualizzarlo in una finestra con un ritardo. SDL ha un timer e può visualizzare le immagini bene.

+0

Grazie per la risposta. Il tuo metodo sembra fattibile, anche se sarebbe molto meglio per me se c'è un modo più diretto. – YBE

2

È possibile creare il processo su gnuplot e inviare i dati al suo stdin insieme ai comandi di stampa. Non sono sicuro di come gestire tale processo in Common Lisp, ma sicuramente posso fare questo in Emacs:

(setf *gnuplot-proc* (start-process "gnuplot" "*gnuplot-proc*" "gnuplot")) 
;;; initiate plotting of data from stdin 
(process-send-string *gnuplot-proc* 
        "plot \"-\" with lines\n") 
;; send your data 
(process-send-string *gnuplot-proc* 
        "5 -1\n4 -3.5\n3 9.5\n") 
;; end of data, after this gnuplot would pop up interactive window 
(process-send-string *gnuplot-proc* "e\n") 

Con tale processo asincrono è facile scrivere qualcosa per renderlo aggiornare interattivamente trama come nuovi dati viene avanti.