;;;; slib-charplot.scm ;;;; Kon Lovett, Mar '20 ;; Issues ;; ;; - synthesize label(s) from data is problematic. (module slib-charplot (;export plot-labels plot-dimensions plot-left-margin xborder-char yborder-char xaxis-char yaxis-char xtick-char bar-char curves-chars histograph plot) (import scheme) (import (chicken module)) (import (only (chicken base) unless include include-relative let-values let-optionals error identity warning make-parameter)) (import (chicken type)) (import (only (chicken platform) features)) (import (only (chicken keyword) string->keyword)) (import (only (srfi 1) last-pair)) (import (srfi 63)) (import slib-arraymap) ;FIXME chicken-install has the feature but after that ... (cond-expand (utf8 (import utf8) (warning "Using utf8 Extension")) (else)) (import slib-compat) ;SRFI 63 (define-type array-strict (struct array)) ;(define-type array (or string vector array-strict)) (define-type maybe-string (or false string)) (define-type plotdims (list fixnum fixnum)) ;(H W) ;(list-of number) ;Y ;(list-of (pair-of number number)) ;(X . Y) ;(list-of (list-of number)) ;(X Y1 ... Yn) ;(list-of (list-of number (list-of number))) ;(X (Y1 ... Yn)) (define-type plotdata (or vector list array-strict)) ;Nd elms (define-type histdata (or (vector-of number) (list-of number))) ;1d elms (define-type plotdata-labeler (plotdata -> string string)) (: plot-labels (#!optional (or false plotdata-labeler) -> plotdata-labeler)) (: plot-dimensions (#!optional (or false plotdims) -> (or false plotdims))) (: plot-left-margin (#!optional (or false fixnum) -> fixnum)) (: xborder-char (#!optional (or false char) -> char)) (: yborder-char (#!optional (or false char) -> char)) (: xaxis-char (#!optional (or false char) -> char)) (: yaxis-char (#!optional (or false char) -> char)) (: xtick-char (#!optional (or false char) -> char)) (: bar-char (#!optional (or false char) -> char)) (: curves-chars (#!optional (or false string) -> string)) #; ;invalid but accurate, just accept no optionals typing (: plot (or (plotdata #!optional string string boolean -> void) ((number -> float) #!optional number number fixnum -> void))) (: plot ((or plotdata (number -> float)) #!rest -> void)) (: histograph (histdata #!optional string -> void)) ;; (include-relative "charplot") ;; Default Plot Labeling (define (default-plot-labels data) (values "" "")) (define plot-labels (make-parameter default-plot-labels (lambda (x) (cond ((not x) default-plot-labels) ((procedure? x) x) (else (warning 'plot-labels "not a procedure or #f" x) (plot-labels) ) ) ) ) ) (define (plotdata-labels data xaxis yaxis) (if (and xaxis yaxis) (values xaxis yaxis) (let-values (((xlabel ylabel) ((plot-labels) data))) (values (or xaxis xlabel) (or yaxis ylabel)) ) ) ) ;; Plot Operations (w/ optional arguments) ;optional axis labels (let ((slib-plot plot)) (set! plot (lambda (data . args) (if (procedure? data) (let-optionals args ((lo 0) (hi 1) (npts 64)) (slib-plot data lo hi npts)) (let-optionals args ((xaxis #f) (yaxis #f) (histogram? #f)) (let-values (((xlabel ylabel) (plotdata-labels data xaxis yaxis))) (slib-plot data xlabel ylabel histogram?)))))) ) ;optional label (let ((slib-histograph histograph)) (set! histograph (lambda (data #!optional (label #f)) (let-values (((xlabel _) (plotdata-labels data label ""))) (slib-histograph data xlabel)))) ) ;; Parameters (replacements for SLIB graph part globals) (define plot-dimensions (make-parameter charplot:dimensions (lambda (x) (cond ((not x) x) ((and (list? x) (<= (length x) 2)) x) (else (warning 'plot-dimensions "not a list (H W)" x) (plot-dimensions) ) ) ) ) ) (define plot-left-margin (make-parameter charplot:left-margin (lambda (x) (cond ((not x) 2) ((and (exact? x) (integer? x) (<= 2 x)) x) (else (warning 'plot-left-margin "not an exact-integer of at least 2" x) (plot-left-margin) ) ) ) ) ) (define-syntax char-warning-predicate (syntax-rules () ((char-warning-predicate ?loc ?def) (lambda (x) (cond ((not x) ?def) ((char? x) x) (else (warning '?loc "not a character") (?loc) ) ) ) ) ) ) (define xborder-char (make-parameter #f (char-warning-predicate xborder-char char:xborder))) (define yborder-char (make-parameter #f (char-warning-predicate yborder-char char:yborder))) (define xaxis-char (make-parameter #f (char-warning-predicate xaxis-char char:xaxis))) (define yaxis-char (make-parameter #f (char-warning-predicate yaxis-char char:yaxis))) (define xtick-char (make-parameter #f (char-warning-predicate xtick-char char:xtick))) (define bar-char (make-parameter #f (char-warning-predicate bar-char char:bar))) (define curves-chars (make-parameter #f (lambda (x) (cond ((not x) char:curves) ((and (string? x) (<= 1 (string-length x))) x) (else (warning 'curves-chars "not a string of at least length 1" x) (curves-chars) ) ) ) ) ) ) ;module slib-charplot