From 1487382015abdd195a10627c506c85bd3a69867c Mon Sep 17 00:00:00 2001 From: Nikolay Puzanov Date: Wed, 5 Jun 2024 22:57:38 +0300 Subject: [PATCH] Initial add gnuplot plotting --- embddr/gnuplot.scm | 114 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 embddr/gnuplot.scm diff --git a/embddr/gnuplot.scm b/embddr/gnuplot.scm new file mode 100644 index 0000000..fb7d8f7 --- /dev/null +++ b/embddr/gnuplot.scm @@ -0,0 +1,114 @@ +(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 (cut format #f "~a" <>) 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"))))