Compare commits

...

2 Commits

Author SHA1 Message Date
Nikolay Puzanov
53408f7bdf Exact numbers is not supported by gnuplot. Fix it 2024-06-06 12:48:19 +03:00
Nikolay Puzanov
1487382015 Initial add gnuplot plotting 2024-06-05 22:57:38 +03:00

117
embddr/gnuplot.scm Normal file
View File

@ -0,0 +1,117 @@
(define-module (embddr gnuplot))
(import (srfi srfi-1)
(srfi srfi-26)
(ice-9 popen)
(ice-9 format))
(export make-plot-xy
plot)
;;;
;;; println
;;;
(define (>> . args)
(when (not (null? args))
(apply format (cons #t args)))
(newline))
;;;
;;; Call app and write to stdin
;;;
(define (with-output-to-spawn cmd f)
(let ((port (open-output-pipe cmd)))
(with-output-to-port port f)
(force-output port)
(close-pipe port)))
;;;
;;; Make plot
;;;
(define* (make-plot-xy #:key
(x #f) ; abscissa
y ; ordinate
(title #f)
(with "lines"))
(let ((x (or x (iota (length y)))))
(if (not (= (length x)
(length y)))
(error "Length of X and Y lists is not equal")
(lambda (key)
(case key
((x) x)
((y) y)
((title) title)
((with) with)
(else #f))))))
;;;
;;; Plot plots
;;;
(define* (plot plots
#:key
(xlabel #f)
(ylabel #f)
(title #f)
(font "Iosevka")
(font-size 11))
(let ((plots (if (list? plots) plots `(,plots))))
(if (not (apply = (map (lambda (plot) (length (plot 'x))) plots)))
(error "Length of plots is not equal")
(let* ((file-port (mkstemp "/tmp/plot-data-XXXXXX" "w"))
(file-name (port-filename file-port)))
;; Write data to temporary file
(with-output-to-port file-port
(lambda ()
(for-each
(cut >> <>)
(map (lambda (sample) (string-join (map
(lambda (x) (number->string
(exact->inexact x)))
sample) " "))
(apply zip (cons ((first plots) 'x)
(map (lambda (plot) (plot 'y)) plots)))))))
(close-port file-port)
;; Call gnuplot
(with-output-to-spawn
"gnuplot"
(lambda ()
(>> "set term x11 enhanced font '~a,~a' persist size 640,480" font font-size)
;; (>> "set output '~a'" "draw.png")
(>> "set grid")
(when xlabel (>> "set xlabel '~a'" xlabel))
(when ylabel (>> "set ylabel '~a'" ylabel))
(when title (>> "set title '~a'" title))
(>> "plot ~a"
(string-join
(map (lambda (plot n)
(format #f "'~a' using 1:~a with ~a~a"
file-name
n
(plot 'with)
(if (plot 'title)
(format #f " title '~a'" (plot 'title))
"")))
plots
(iota (length plots) 2))
",\\\n"))))
;; Delete temporary file
(delete-file file-name)))))
;; (define (main args)
;; (plot
;; `(,(make-plot-xy
;; #:x (iota 17 20 -1)
;; #:y '(1 2 3 4 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1)
;; #:title "plot A"
;; #:with "lines lw 2")
;; ,(make-plot-xy
;; #:x (iota 17 20 -1)
;; #:y (map (cut * -0.5 <>) '(1 2 3 4 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 0 1))
;; #:title "plot B"
;; #:with "lines"))))