(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"))))