Added "Axis Transforms and Ticks" doc page
This commit is contained in:
parent
5a3c78a998
commit
723a54a4d9
|
@ -15,23 +15,24 @@
|
|||
[(invertible-function f2 g2) f2])
|
||||
(invertible-function (compose f1 f2) (compose g2 g1))))
|
||||
|
||||
(defproc (invertible-inverse [h invertible-function?]) invertible-function?
|
||||
(defproc (invertible-inverse [h invertible-function?]) invertible-function? #:document-body
|
||||
(match-define (invertible-function f g) h)
|
||||
(invertible-function g f))
|
||||
|
||||
(defcontract axis-transform/c (real? real? invertible-function? . -> . invertible-function?))
|
||||
|
||||
(defproc (id-transform [x-min real?] [x-max real?] [old-function invertible-function?]
|
||||
) invertible-function?
|
||||
old-function)
|
||||
(defthing id-transform axis-transform/c
|
||||
(λ (x-min x-max old-function) old-function))
|
||||
|
||||
(defthing id-function invertible-function? (invertible-function (λ (x) x) (λ (x) x)))
|
||||
|
||||
(defproc (apply-axis-transform [t axis-transform/c] [x-min real?] [x-max real?]) invertible-function?
|
||||
(defproc (apply-axis-transform [t axis-transform/c] [x-min real?] [x-max real?]
|
||||
) invertible-function? #:document-body
|
||||
(t x-min x-max id-function))
|
||||
|
||||
;; Turns any total, surjective, monotone real function and its inverse into an axis transform
|
||||
(defproc (make-axis-transform [f (real? . -> . real?)] [g (real? . -> . real?)]) axis-transform/c
|
||||
(defproc (make-axis-transform [fun invertible-function?]) axis-transform/c
|
||||
(match-define (invertible-function f g) fun)
|
||||
(λ (x-min x-max old-function)
|
||||
(define fx-min (f x-min))
|
||||
(define fx-scale (/ (- x-max x-min) (- (f x-max) fx-min)))
|
||||
|
@ -46,24 +47,28 @@
|
|||
(λ (x-min x-max old-function)
|
||||
(t1 x-min x-max (t2 x-min x-max old-function))))
|
||||
|
||||
(defproc (axis-transform-append [t1 axis-transform/c] [t2 axis-transform/c] [x-mid real?]
|
||||
(defproc (axis-transform-append [t1 axis-transform/c] [t2 axis-transform/c] [mid real?]
|
||||
) axis-transform/c
|
||||
(λ (x-min x-max old-function)
|
||||
(match-define (invertible-function old-f old-g) old-function)
|
||||
(let ([x-mid (old-f x-mid)])
|
||||
(cond [(x-mid . >= . x-max) (t1 x-min x-max old-function)]
|
||||
[(x-mid . <= . x-min) (t2 x-min x-max old-function)]
|
||||
(let ([mid (old-f mid)])
|
||||
(cond [(mid . >= . x-max) (t1 x-min x-max old-function)]
|
||||
[(mid . <= . x-min) (t2 x-min x-max old-function)]
|
||||
[else
|
||||
(match-define (invertible-function f1 g1) (t1 x-min x-mid old-function))
|
||||
(match-define (invertible-function f2 g2) (t2 x-mid x-max old-function))
|
||||
((make-axis-transform (λ (x) (cond [((old-f x) . < . x-mid) (f1 x)]
|
||||
[else (f2 x)]))
|
||||
(λ (x) (cond [(x . < . x-mid) (g1 x)]
|
||||
[else (g2 x)])))
|
||||
(match-define (invertible-function f1 g1) (t1 x-min mid old-function))
|
||||
(match-define (invertible-function f2 g2) (t2 mid x-max old-function))
|
||||
((make-axis-transform
|
||||
(invertible-function
|
||||
(λ (x) (cond [((old-f x) . < . mid) (f1 x)]
|
||||
[else (f2 x)]))
|
||||
(λ (x) (cond [(x . < . mid) (g1 x)]
|
||||
[else (g2 x)]))))
|
||||
x-min x-max id-function)]))))
|
||||
|
||||
(defproc (axis-transform-bound [t axis-transform/c] [x-min real?] [x-max real?]) axis-transform/c
|
||||
(axis-transform-append (axis-transform-append id-transform t x-min) id-transform x-max))
|
||||
(defproc (axis-transform-bound [t axis-transform/c] [a real?] [b real?]
|
||||
) axis-transform/c #:document-body
|
||||
(axis-transform-append
|
||||
(axis-transform-append id-transform t a) id-transform b))
|
||||
|
||||
;; ===================================================================================================
|
||||
;; Specific axis transforms
|
||||
|
@ -107,20 +112,21 @@
|
|||
(define (real-exp x)
|
||||
(flexp (exact->inexact x)))
|
||||
|
||||
(defproc (log-transform [x-min real?] [x-max real?] [old-function invertible-function?]
|
||||
) invertible-function?
|
||||
(when ((exact->inexact x-min) . <= . 0)
|
||||
(raise-type-error 'log-transform "positive real" 0 x-min x-max))
|
||||
((make-axis-transform real-log real-exp) x-min x-max old-function))
|
||||
(defthing log-transform axis-transform/c
|
||||
(λ (x-min x-max old-function)
|
||||
(when ((exact->inexact x-min) . <= . 0)
|
||||
(raise-type-error 'log-transform "positive real" 0 x-min x-max))
|
||||
((make-axis-transform (invertible-function real-log real-exp)) x-min x-max old-function)))
|
||||
|
||||
(defproc (cbrt-transform [x-min real?] [x-max real?] [old-function invertible-function?]
|
||||
) invertible-function?
|
||||
((make-axis-transform cbrt cube) x-min x-max old-function))
|
||||
(defthing cbrt-transform axis-transform/c
|
||||
(λ (x-min x-max old-function)
|
||||
((make-axis-transform (invertible-function cbrt cube)) x-min x-max old-function)))
|
||||
|
||||
(defproc (hand-drawn-transform [freq (>/c 0)]) axis-transform/c
|
||||
(λ (x-min x-max old-function)
|
||||
(define d (/ freq (- x-max x-min)))
|
||||
((make-axis-transform (sine-diag d) (sine-diag-inv d)) x-min x-max old-function)))
|
||||
((make-axis-transform (invertible-function (sine-diag d) (sine-diag-inv d)))
|
||||
x-min x-max old-function)))
|
||||
|
||||
;; ===================================================================================================
|
||||
|
||||
|
@ -132,8 +138,7 @@
|
|||
[(x . > . b) (+ (- x d) ds)]
|
||||
[else (+ a (* (- x a) s))])))
|
||||
|
||||
(defproc (stretch-transform [a real?] [b real?] [scale (and/c real? (not/c (=/c 0)))]
|
||||
) axis-transform/c
|
||||
(defproc (stretch-transform [a real?] [b real?] [scale (>/c 0)]) axis-transform/c
|
||||
(when (a . > . b) (error 'stretch-transform "expected a <= b; given ~e and ~e" a b))
|
||||
(λ (x-min x-max old-function)
|
||||
(match-define (invertible-function old-f old-g) old-function)
|
||||
|
@ -141,7 +146,7 @@
|
|||
[b (old-f b)])
|
||||
(define f (stretch a b scale))
|
||||
(define g (stretch (f a) (f b) (/ 1 scale)))
|
||||
((make-axis-transform f g) x-min x-max old-function))))
|
||||
((make-axis-transform (invertible-function f g)) x-min x-max old-function))))
|
||||
|
||||
(defproc (collapse-transform [a real?] [b real?]) axis-transform/c
|
||||
(when (a . > . b) (error 'stretch-transform "expected a <= b; given ~e and ~e" a b))
|
||||
|
@ -157,4 +162,4 @@
|
|||
(define (g x) (cond [(x . < . center) (- x 1/2size)]
|
||||
[(x . > . center) (+ x 1/2size)]
|
||||
[else center]))
|
||||
((make-axis-transform f g) x-min x-max old-function))))
|
||||
((make-axis-transform (invertible-function f g)) x-min x-max old-function))))
|
||||
|
|
|
@ -41,16 +41,6 @@
|
|||
(defparam plot-y-far-axis? boolean? #t)
|
||||
(defparam plot-z-far-axis? boolean? #t)
|
||||
|
||||
(defparam plot-x-max-ticks exact-positive-integer? 5)
|
||||
(defparam plot-y-max-ticks exact-positive-integer? 5)
|
||||
(defparam plot-z-max-ticks exact-positive-integer? 8)
|
||||
(defparam plot-d-max-ticks exact-positive-integer? 6)
|
||||
(defparam plot-r-max-ticks exact-positive-integer? 8)
|
||||
|
||||
(defparam plot-x-far-max-ticks exact-positive-integer? 5)
|
||||
(defparam plot-y-far-max-ticks exact-positive-integer? 5)
|
||||
(defparam plot-z-far-max-ticks exact-positive-integer? 8)
|
||||
|
||||
(defparam plot-decorations? boolean? #t)
|
||||
|
||||
(define-parameter-group plot-axes?
|
||||
|
@ -59,14 +49,6 @@
|
|||
plot-z-axis? plot-z-far-axis?)
|
||||
#:struct list)
|
||||
|
||||
(define-parameter-group plot-max-ticks
|
||||
(plot-x-max-ticks plot-x-far-max-ticks
|
||||
plot-y-max-ticks plot-y-far-max-ticks
|
||||
plot-z-max-ticks plot-z-far-max-ticks
|
||||
plot-d-max-ticks
|
||||
plot-r-max-ticks)
|
||||
#:struct list)
|
||||
|
||||
(define-parameter-group plot-appearance
|
||||
(plot-width
|
||||
plot-height
|
||||
|
@ -75,7 +57,7 @@
|
|||
plot-line-width plot-tick-size
|
||||
plot-font-size plot-font-family
|
||||
plot-legend-anchor plot-legend-box-alpha
|
||||
plot-axes? plot-max-ticks plot-decorations?
|
||||
plot-axes? plot-decorations?
|
||||
plot-animating?))
|
||||
|
||||
(defproc (pen-gap) real? #:document-body
|
||||
|
@ -135,9 +117,9 @@
|
|||
|
||||
(defparam plot-x-ticks ticks? (linear-ticks))
|
||||
(defparam plot-y-ticks ticks? (linear-ticks))
|
||||
(defparam plot-z-ticks ticks? (linear-ticks))
|
||||
(defparam plot-d-ticks ticks? (linear-ticks #:divisors '(1 2 4 5)))
|
||||
(defparam plot-r-ticks ticks? (linear-ticks))
|
||||
(defparam plot-z-ticks ticks? (linear-ticks #:number 8))
|
||||
(defparam plot-d-ticks ticks? (linear-ticks #:number 6 #:divisors '(1 2 4 5)))
|
||||
(defparam plot-r-ticks ticks? (linear-ticks #:number 8))
|
||||
|
||||
(defparam plot-x-far-ticks ticks? (ticks-mimic plot-x-ticks))
|
||||
(defparam plot-y-far-ticks ticks? (ticks-mimic plot-y-ticks))
|
||||
|
@ -151,30 +133,6 @@
|
|||
(define-parameter-group plot-axes (plot-x-axis plot-y-axis plot-z-axis plot-d-ticks plot-r-ticks)
|
||||
#:struct list)
|
||||
|
||||
(defproc (default-x-ticks [x-min real?] [x-max real?]) (listof tick?) #:document-body
|
||||
((plot-x-ticks) x-min x-max (plot-x-max-ticks)))
|
||||
|
||||
(defproc (default-y-ticks [y-min real?] [y-max real?]) (listof tick?) #:document-body
|
||||
((plot-y-ticks) y-min y-max (plot-y-max-ticks)))
|
||||
|
||||
(defproc (default-z-ticks [z-min real?] [z-max real?]) (listof tick?) #:document-body
|
||||
((plot-z-ticks) z-min z-max (plot-z-max-ticks)))
|
||||
|
||||
(defproc (default-d-ticks [d-min real?] [d-max real?]) (listof tick?) #:document-body
|
||||
((plot-d-ticks) d-min d-max (plot-d-max-ticks)))
|
||||
|
||||
(defproc (default-r-ticks [r-min real?] [r-max real?]) (listof tick?) #:document-body
|
||||
((plot-r-ticks) r-min r-max (plot-r-max-ticks)))
|
||||
|
||||
(defproc (default-x-far-ticks [x-min real?] [x-max real?]) (listof tick?) #:document-body
|
||||
((plot-x-far-ticks) x-min x-max (plot-x-far-max-ticks)))
|
||||
|
||||
(defproc (default-y-far-ticks [y-min real?] [y-max real?]) (listof tick?) #:document-body
|
||||
((plot-y-far-ticks) y-min y-max (plot-y-far-max-ticks)))
|
||||
|
||||
(defproc (default-z-far-ticks [z-min real?] [z-max real?]) (listof tick?) #:document-body
|
||||
((plot-z-far-ticks) z-min z-max (plot-z-far-max-ticks)))
|
||||
|
||||
;; ===================================================================================================
|
||||
|
||||
(define-parameter-group plot-parameters
|
||||
|
|
|
@ -25,12 +25,12 @@
|
|||
(λ (r)
|
||||
(match r
|
||||
[(vector (ivl xa xb) (ivl ya yb))
|
||||
(values (default-x-ticks xa xb) (default-x-far-ticks xa xb)
|
||||
(default-y-ticks ya yb) (default-y-far-ticks ya yb))]
|
||||
(values ((plot-x-ticks) xa xb) ((plot-x-far-ticks) xa xb)
|
||||
((plot-y-ticks) ya yb) ((plot-y-far-ticks) ya yb))]
|
||||
[(vector (ivl xa xb) (ivl ya yb) (ivl za zb))
|
||||
(values (default-x-ticks xa xb) (default-x-far-ticks xa xb)
|
||||
(default-y-ticks ya yb) (default-y-far-ticks ya yb)
|
||||
(default-z-ticks za zb) (default-z-far-ticks za zb))]
|
||||
(values ((plot-x-ticks) xa xb) ((plot-x-far-ticks) xa xb)
|
||||
((plot-y-ticks) ya yb) ((plot-y-far-ticks) ya yb)
|
||||
((plot-z-ticks) za zb) ((plot-z-far-ticks) za zb))]
|
||||
[_ (raise-type-error 'default-ticks-fun "2- or 3-vector of ivl" r)])))
|
||||
|
||||
(defproc (function-bounds-fun [f sampler/c] [samples exact-nonnegative-integer?]) bounds-fun/c
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
(define epsilon (expt 10 (- (digits-for-range z-min z-max))))
|
||||
(match-define (ticks layout format) (plot-z-ticks))
|
||||
(define ts
|
||||
(cond [(eq? levels 'auto) (filter pre-tick-major? (layout z-min z-max (plot-z-max-ticks)))]
|
||||
(cond [(eq? levels 'auto) (filter pre-tick-major? (layout z-min z-max))]
|
||||
[else (define zs (cond [(list? levels) (filter (λ (z) (<= z-min z z-max)) levels)]
|
||||
[else (linear-seq z-min z-max levels #:start? #f #:end? #f)]))
|
||||
(map (λ (z) (pre-tick z #t)) zs)]))
|
||||
|
@ -56,7 +56,7 @@
|
|||
(define epsilon (expt 10 (- (digits-for-range d-min d-max))))
|
||||
(match-define (ticks layout format) (plot-d-ticks))
|
||||
(define ts
|
||||
(cond [(eq? levels 'auto) (filter pre-tick-major? (layout d-min d-max (plot-d-max-ticks)))]
|
||||
(cond [(eq? levels 'auto) (filter pre-tick-major? (layout d-min d-max))]
|
||||
[else (define ds (cond [(list? levels) (filter (λ (d) (<= d-min d d-max)) levels)]
|
||||
[else (linear-seq d-min d-max levels #:start? #f #:end? #f)]))
|
||||
(map (λ (d) (pre-tick d #t)) ds)]))
|
||||
|
|
|
@ -20,17 +20,16 @@
|
|||
|
||||
(struct ticks (layout format) #:transparent
|
||||
#:property prop:procedure
|
||||
(λ (t x-min x-max max-ticks)
|
||||
(λ (t x-min x-max)
|
||||
(match-define (ticks layout format) t)
|
||||
(define ts (layout x-min x-max max-ticks))
|
||||
(define ts (layout x-min x-max))
|
||||
(match-define (list (pre-tick xs majors) ...) ts)
|
||||
(map tick xs majors (format x-min x-max ts))))
|
||||
|
||||
(defcontract ticks-layout/c
|
||||
(real? real? exact-positive-integer? . -> . (listof pre-tick?)))
|
||||
(defcontract ticks-layout/c (real? real? . -> . (listof pre-tick?)))
|
||||
(defcontract ticks-format/c (real? real? (listof pre-tick?) . -> . (listof string?)))
|
||||
|
||||
(defcontract ticks-format/c
|
||||
(real? real? (listof pre-tick?) . -> . (listof string?)))
|
||||
(defparam ticks-default-number exact-positive-integer? 5)
|
||||
|
||||
;; ===================================================================================================
|
||||
;; Helpers
|
||||
|
@ -108,11 +107,12 @@
|
|||
(define minor-xs (linear-minor-values/step major-xs step (- n 1)))
|
||||
(values major-xs (filter (λ (x) (<= x-min x x-max)) minor-xs))))
|
||||
|
||||
(defproc (linear-ticks-layout [#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
(defproc (linear-ticks-layout [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
[#:divisors divisors (listof exact-positive-integer?) '(1 2 5)]
|
||||
) ticks-layout/c
|
||||
(λ (x-min x-max max-ticks)
|
||||
(define-values (major-xs minor-xs) (linear-tick-values x-min x-max max-ticks base divisors))
|
||||
(λ (x-min x-max)
|
||||
(define-values (major-xs minor-xs) (linear-tick-values x-min x-max number base divisors))
|
||||
(tick-values->pre-ticks major-xs minor-xs)))
|
||||
|
||||
(defproc (linear-ticks-format) ticks-format/c
|
||||
|
@ -123,32 +123,41 @@
|
|||
(for/list ([t (in-list ts)])
|
||||
(real->plot-label (pre-tick-value t) digits)))))
|
||||
|
||||
(defproc (linear-ticks [#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
[#:divisors divisors (listof exact-positive-integer?) '(1 2 5)]) ticks?
|
||||
(ticks (linear-ticks-layout #:base base #:divisors divisors)
|
||||
(defproc (linear-ticks [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
[#:divisors divisors (listof exact-positive-integer?) '(1 2 5)]
|
||||
) ticks? #:document-body
|
||||
(ticks (linear-ticks-layout #:number number #:base base
|
||||
#:divisors divisors)
|
||||
(linear-ticks-format)))
|
||||
|
||||
;; ===================================================================================================
|
||||
;; No ticks
|
||||
|
||||
(defproc (no-ticks-layout) ticks-layout/c
|
||||
(λ (x-min x-max max-ticks) empty))
|
||||
(defthing no-ticks-layout ticks-layout/c #:document-value
|
||||
(λ (x-min x-max) empty))
|
||||
|
||||
(defproc (no-ticks) ticks?
|
||||
(ticks (no-ticks-layout) (linear-ticks-format)))
|
||||
(defthing no-ticks-format ticks-format/c #:document-value
|
||||
(λ (x-min x-max pre-ticks)
|
||||
(map (λ (_) "") pre-ticks)))
|
||||
|
||||
(defthing no-ticks ticks? #:document-value
|
||||
(ticks no-ticks-layout no-ticks-format))
|
||||
|
||||
;; ===================================================================================================
|
||||
;; Exponential ticks (for log scale)
|
||||
|
||||
(defproc (log-ticks-layout [#:base base (and/c exact-integer? (>=/c 2)) 10]) ticks-layout/c
|
||||
(λ (x-min x-max max-ticks)
|
||||
(defproc (log-ticks-layout [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
) ticks-layout/c
|
||||
(λ (x-min x-max)
|
||||
(with-exact-bounds
|
||||
x-min x-max
|
||||
(when ((exact->inexact x-min) . <= . 0)
|
||||
(raise-type-error 'log-ticks-layout "positive real" 0 x-min x-max))
|
||||
(define log-start (ceiling-log/base base x-min))
|
||||
(define log-end (floor-log/base base x-max))
|
||||
(define skip (max 1 (ceiling (/ (+ 1 (- log-end log-start)) max-ticks))))
|
||||
(define skip (max 1 (ceiling (/ (+ 1 (- log-end log-start)) number))))
|
||||
(filter (λ (t) (<= x-min (pre-tick-value t) x-max))
|
||||
(append*
|
||||
(for/list ([log-x (in-range (- log-start 1) (+ log-end 2))]
|
||||
|
@ -177,8 +186,10 @@
|
|||
(real->plot-label (/ x (expt base log-x)) base-digits)
|
||||
(major-str))])))))
|
||||
|
||||
(defproc (log-ticks [#:base base (and/c exact-integer? (>=/c 2)) 10]) ticks?
|
||||
(ticks (log-ticks-layout #:base base)
|
||||
(defproc (log-ticks [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
) ticks? #:document-body
|
||||
(ticks (log-ticks-layout #:number number #:base base)
|
||||
(log-ticks-format #:base base)))
|
||||
|
||||
;; ===================================================================================================
|
||||
|
@ -213,48 +224,40 @@
|
|||
;; ===================================================================================================
|
||||
;; Date ticks
|
||||
|
||||
(define 12h-descending-date-ticks-formats
|
||||
'("~Y-~m-~d ~I:~M:~f ~p"
|
||||
"~Y-~m-~d ~I:~M ~p"
|
||||
"~Y-~m-~d ~I ~p"
|
||||
"~Y-~m-~d"
|
||||
"~Y-~m"
|
||||
"~Y"
|
||||
|
||||
"~m-~d ~I:~M:~f ~p"
|
||||
"~m-~d ~I:~M ~p"
|
||||
"~m-~d ~I ~p"
|
||||
"~m-~d"
|
||||
|
||||
"~I:~M:~f ~p"
|
||||
"~I:~M ~p"
|
||||
"~I ~p"
|
||||
|
||||
"~M:~fs"
|
||||
"~Mm"
|
||||
|
||||
"~fs"))
|
||||
|
||||
(define 24h-descending-date-ticks-formats
|
||||
(defthing 24h-descending-date-ticks-formats (listof string?) #:document-value
|
||||
'("~Y-~m-~d ~H:~M:~f"
|
||||
"~Y-~m-~d ~H:~M"
|
||||
"~Y-~m-~d ~Hh"
|
||||
"~Y-~m-~d"
|
||||
"~Y-~m"
|
||||
"~Y"
|
||||
|
||||
"~m-~d ~H:~M:~f"
|
||||
"~m-~d ~H:~M"
|
||||
"~m-~d ~Hh"
|
||||
"~m-~d"
|
||||
|
||||
"~H:~M:~f"
|
||||
"~H:~M"
|
||||
"~Hh"
|
||||
|
||||
"~M:~fs"
|
||||
"~Mm"
|
||||
|
||||
"~fs"))
|
||||
|
||||
(defthing 12h-descending-date-ticks-formats (listof string?) #:document-value
|
||||
'("~Y-~m-~d ~I:~M:~f ~p"
|
||||
"~Y-~m-~d ~I:~M ~p"
|
||||
"~Y-~m-~d ~I ~p"
|
||||
"~Y-~m-~d"
|
||||
"~Y-~m"
|
||||
"~Y"
|
||||
"~m-~d ~I:~M:~f ~p"
|
||||
"~m-~d ~I:~M ~p"
|
||||
"~m-~d ~I ~p"
|
||||
"~m-~d"
|
||||
"~I:~M:~f ~p"
|
||||
"~I:~M ~p"
|
||||
"~I ~p"
|
||||
"~M:~fs"
|
||||
"~Mm"
|
||||
"~fs"))
|
||||
|
||||
(defparam date-ticks-formats (listof string?) 24h-descending-date-ticks-formats)
|
||||
|
@ -316,9 +319,10 @@
|
|||
(define major-xs (linear-major-values/step x-min x-max step))
|
||||
(values (map date-round major-xs) empty)))
|
||||
|
||||
(defproc (date-ticks-layout) ticks-layout/c
|
||||
(λ (x-min x-max max-ticks)
|
||||
(define-values (major-xs minor-xs) (date-tick-values x-min x-max max-ticks))
|
||||
(defproc (date-ticks-layout [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
) ticks-layout/c
|
||||
(λ (x-min x-max)
|
||||
(define-values (major-xs minor-xs) (date-tick-values x-min x-max number))
|
||||
(tick-values->pre-ticks major-xs minor-xs)))
|
||||
|
||||
(defproc (date-ticks-format [#:formats formats (listof string?) (date-ticks-formats)]) ticks-format/c
|
||||
|
@ -336,29 +340,40 @@
|
|||
(define fmt-list (choose-format-list formatter fmt-lists (list last-x x)))
|
||||
(string-append* (apply-formatter formatter fmt-list x))))]))))
|
||||
|
||||
(defproc (date-ticks [#:formats formats (listof string?) (date-ticks-formats)]) ticks?
|
||||
(ticks (date-ticks-layout)
|
||||
(defproc (date-ticks [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:formats formats (listof string?) (date-ticks-formats)]
|
||||
) ticks? #:document-body
|
||||
(ticks (date-ticks-layout #:number number)
|
||||
(date-ticks-format #:formats formats)))
|
||||
|
||||
;; ===================================================================================================
|
||||
;; Time ticks
|
||||
|
||||
(define descending-time-ticks-formats
|
||||
(defthing 24h-descending-time-ticks-formats (listof string?) #:document-value
|
||||
'("~dd ~H:~M:~f"
|
||||
"~dd ~H:~M"
|
||||
"~dd ~Hh"
|
||||
"~dd"
|
||||
|
||||
"~H:~M:~f"
|
||||
"~H:~M"
|
||||
"~Hh"
|
||||
|
||||
"~M:~fs"
|
||||
"~Mm"
|
||||
|
||||
"~fs"))
|
||||
|
||||
(defparam time-ticks-formats (listof string?) descending-time-ticks-formats)
|
||||
(defthing 12h-descending-time-ticks-formats (listof string?) #:document-value
|
||||
'("~dd ~I:~M:~f ~p"
|
||||
"~dd ~I:~M ~p"
|
||||
"~dd ~I ~p"
|
||||
"~dd"
|
||||
"~I:~M:~f ~p"
|
||||
"~I:~M ~p"
|
||||
"~I ~p"
|
||||
"~M:~fs"
|
||||
"~Mm"
|
||||
"~fs"))
|
||||
|
||||
(defparam time-ticks-formats (listof string?) 24h-descending-time-ticks-formats)
|
||||
|
||||
;; Tick steps to try, in seconds
|
||||
(define time-steps
|
||||
|
@ -408,9 +423,10 @@
|
|||
(define major-xs (linear-major-values/step x-min x-max step))
|
||||
(values major-xs empty)))
|
||||
|
||||
(defproc (time-ticks-layout) ticks-layout/c
|
||||
(λ (x-min x-max max-ticks)
|
||||
(define-values (major-xs minor-xs) (time-tick-values x-min x-max max-ticks))
|
||||
(defproc (time-ticks-layout [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
) ticks-layout/c
|
||||
(λ (x-min x-max)
|
||||
(define-values (major-xs minor-xs) (time-tick-values x-min x-max number))
|
||||
(tick-values->pre-ticks major-xs minor-xs)))
|
||||
|
||||
(defproc (time-ticks-format [#:formats formats (listof string?) (time-ticks-formats)]) ticks-format/c
|
||||
|
@ -428,8 +444,10 @@
|
|||
(define fmt-list (choose-format-list formatter fmt-lists (list last-x x)))
|
||||
(string-append* (apply-formatter formatter fmt-list x))))]))))
|
||||
|
||||
(defproc (time-ticks [#:formats formats (listof string?) (time-ticks-formats)]) ticks?
|
||||
(ticks (time-ticks-layout)
|
||||
(defproc (time-ticks [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:formats formats (listof string?) (time-ticks-formats)]
|
||||
) ticks? #:document-body
|
||||
(ticks (time-ticks-layout #:number number)
|
||||
(time-ticks-format #:formats formats)))
|
||||
|
||||
;; ===================================================================================================
|
||||
|
@ -462,33 +480,36 @@
|
|||
(define unit-x (/ (pre-tick-value t) unit))
|
||||
(format format-str (real->plot-label unit-x digits #f))))))
|
||||
|
||||
(defproc (bit/byte-ticks [#:size size (or/c 'byte 'bit) 'byte]
|
||||
[#:kind kind (or/c 'CS 'SI) 'CS]) ticks?
|
||||
(define layout
|
||||
(case kind
|
||||
[(SI) (linear-ticks-layout #:base 10 #:divisors '(1 2 5))]
|
||||
[else (linear-ticks-layout #:base 2 #:divisors '(1 2))]))
|
||||
(ticks layout (bit/byte-ticks-format #:size size #:kind kind)))
|
||||
(defproc (bit/byte-ticks [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:size size (or/c 'byte 'bit) 'byte]
|
||||
[#:kind kind (or/c 'CS 'SI) 'CS]
|
||||
) ticks? #:document-body
|
||||
(define si? (eq? kind 'SI))
|
||||
(ticks (linear-ticks-layout #:number number #:base (if si? 10 2)
|
||||
#:divisors (if si? '(1 2 5) '(1 2)))
|
||||
(bit/byte-ticks-format #:size size #:kind kind)))
|
||||
|
||||
;; ===================================================================================================
|
||||
;; Currency
|
||||
|
||||
;; US "short scale" suffixes
|
||||
(define us-currency-scales '("" "K" "M" "B" "T"))
|
||||
;; The UK officially uses the short scale now
|
||||
;; Million is abbreviated "m" instead of "mn" because "mn" stands for minutes; also, the Daily
|
||||
;; Telegraph Style Guide totally says to use "m"
|
||||
(define uk-currency-scales '("" "k" "m" "bn" "tr"))
|
||||
(defthing us-currency-scales (listof string?) #:document-value '("" "K" "M" "B" "T"))
|
||||
;; The UK officially uses the short scale since 1974
|
||||
;; Million is abbreviated "m" instead of "mn" because "mn" stands for minutes
|
||||
(defthing uk-currency-scales (listof string?) #:document-value '("" "k" "m" "bn" "tr"))
|
||||
;; European countries use the long scale: million, milliard, billion
|
||||
(define eu-currency-scales '("" "K" "M" "Md" "B"))
|
||||
;; The larger the scale suffixes get, the less standardized they are; so we stop at trillion (short)
|
||||
(defthing eu-currency-scales (listof string?) #:document-value '("" "K" "M" "Md" "B"))
|
||||
;; The larger the scale suffixes get, the less standardized they are; so we stop at billion (long)
|
||||
|
||||
;; US negative amounts are in parenthesis:
|
||||
(define us-currency-formats '("~$~w.~f~s" "(~$~w.~f~s)" "~$0"))
|
||||
(defthing us-currency-formats (list/c string? string? string?) #:document-value
|
||||
'("~$~w.~f~s" "(~$~w.~f~s)" "~$0"))
|
||||
;; The UK is more reasonable, using a negative sign for negative amounts:
|
||||
(define uk-currency-formats '("~$~w.~f ~s" "-~$~w.~f ~s" "~$0"))
|
||||
(defthing uk-currency-formats (list/c string? string? string?) #:document-value
|
||||
'("~$~w.~f~s" "-~$~w.~f~s" "~$0"))
|
||||
;; The more common EU format (e.g. France, Germany, Italy, Spain):
|
||||
(define eu-currency-formats '("~w,~f ~s~$" "-~w,~f ~s~$" "0 ~$"))
|
||||
(defthing eu-currency-formats (list/c string? string? string?) #:document-value
|
||||
'("~w,~f ~s~$" "-~w,~f ~s~$" "0 ~$"))
|
||||
|
||||
(defparam currency-ticks-scales (listof string?) us-currency-scales)
|
||||
(defparam currency-ticks-formats (list/c string? string? string?) us-currency-formats)
|
||||
|
@ -546,22 +567,19 @@
|
|||
(apply-formatter formatter format-list
|
||||
(amount-data sign whole frac unit suffix)))))))
|
||||
|
||||
(defproc (currency-ticks-layout) ticks-layout/c
|
||||
(linear-ticks-layout #:base 10 #:divisors '(1 2 4 5)))
|
||||
|
||||
(defproc (currency-ticks [#:kind kind (or/c string? symbol?) 'USD]
|
||||
(defproc (currency-ticks [#:number number exact-positive-integer? (ticks-default-number)]
|
||||
[#:kind kind (or/c string? symbol?) 'USD]
|
||||
[#:scales scales (listof string?) (currency-ticks-scales)]
|
||||
[#:formats formats (list/c string? string? string?) (currency-ticks-formats)]
|
||||
) ticks?
|
||||
(ticks (currency-ticks-layout)
|
||||
(currency-ticks-format #:kind kind #:scales scales #:formats formats)))
|
||||
) ticks? #:document-body
|
||||
(ticks (linear-ticks-layout #:number number #:base 10
|
||||
#:divisors '(1 2 4 5))
|
||||
(currency-ticks-format #:kind kind #:scales scales
|
||||
#:formats formats)))
|
||||
|
||||
;; ===================================================================================================
|
||||
;; Fractions
|
||||
|
||||
(defparam fraction-ticks-base (and/c exact-integer? (>=/c 2)) 10)
|
||||
(defparam fraction-ticks-divisors (listof exact-positive-integer?) '(1 2 3 4 5))
|
||||
|
||||
(define (format-fraction x)
|
||||
(cond [(inexact? x) (format-fraction (inexact->exact x))]
|
||||
[(x . < . 0) (format "-~a" (format-fraction (- x)))]
|
||||
|
@ -580,9 +598,9 @@
|
|||
(for/list ([t (in-list ts)])
|
||||
(format-fraction (pre-tick-value t)))))
|
||||
|
||||
(defproc (fraction-ticks [#:base base (and/c exact-integer? (>=/c 2)) (fraction-ticks-base)]
|
||||
[#:divisors divisors (listof exact-positive-integer?)
|
||||
(fraction-ticks-divisors)]) ticks?
|
||||
(defproc (fraction-ticks [#:base base (and/c exact-integer? (>=/c 2)) 10]
|
||||
[#:divisors divisors (listof exact-positive-integer?) '(1 2 3 4 5)]
|
||||
) ticks? #:document-body
|
||||
(ticks (linear-ticks #:base base #:divisors divisors)
|
||||
(fraction-ticks-format)))
|
||||
|
||||
|
@ -590,16 +608,14 @@
|
|||
;; Tick combinators
|
||||
|
||||
(defproc (ticks-mimic [thunk (-> ticks?)]) ticks?
|
||||
(ticks (λ (x-min x-max max-ticks)
|
||||
((ticks-layout (thunk)) x-min x-max max-ticks))
|
||||
(λ (x-min x-max ts)
|
||||
((ticks-format (thunk)) x-min x-max ts))))
|
||||
(ticks (λ (x-min x-max) ((ticks-layout (thunk)) x-min x-max))
|
||||
(λ (x-min x-max ts) ((ticks-format (thunk)) x-min x-max ts))))
|
||||
|
||||
(defproc (ticks-scale [t ticks?] [fun invertible-function?]) ticks?
|
||||
(match-define (invertible-function f g) fun)
|
||||
(match-define (ticks layout format) t)
|
||||
(ticks (λ (x-min x-max max-ticks)
|
||||
(define ts (layout (f x-min) (f x-max) max-ticks))
|
||||
(ticks (λ (x-min x-max)
|
||||
(define ts (layout (f x-min) (f x-max)))
|
||||
(for/list ([t (in-list ts)])
|
||||
(match-define (pre-tick x major?) t)
|
||||
(pre-tick (g x) major?)))
|
||||
|
@ -611,13 +627,13 @@
|
|||
|
||||
(defproc (ticks-add [t ticks?] [xs (listof real?)] [major? boolean? #t]) ticks?
|
||||
(match-define (ticks layout format) t)
|
||||
(ticks (λ (x-min x-max max-ticks)
|
||||
(append (layout x-min x-max max-ticks)
|
||||
(ticks (λ (x-min x-max)
|
||||
(append (layout x-min x-max)
|
||||
(for/list ([x (in-list xs)])
|
||||
(pre-tick x major?))))
|
||||
format))
|
||||
|
||||
(defproc (linear-scale [m real?] [b real? 0]) invertible-function?
|
||||
(defproc (linear-scale [m real?] [b real? 0]) invertible-function? #:document-body
|
||||
(invertible-function (λ (x) (+ (* m x) b))
|
||||
(λ (y) (/ (- y b) m))))
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
"plot3d/plot-area.rkt"
|
||||
(prefix-in new. (only-in "main.rkt"
|
||||
x-axis y-axis
|
||||
default-x-ticks default-y-ticks default-z-ticks
|
||||
plot-x-ticks plot-y-ticks plot-z-ticks
|
||||
points error-bars vector-field
|
||||
plot-title plot-x-label plot-y-label plot-z-label
|
||||
plot-foreground plot-background
|
||||
|
@ -75,8 +75,8 @@
|
|||
[#:lncolor lncolor (list/c byte? byte? byte?) '(255 0 0)]
|
||||
[#:out-file out-file (or/c path-string? output-port? #f) #f]
|
||||
) (is-a?/c image-snip%)
|
||||
(define x-ticks (new.default-x-ticks x-min x-max))
|
||||
(define y-ticks (new.default-y-ticks y-min y-max))
|
||||
(define x-ticks ((new.plot-x-ticks) x-min x-max))
|
||||
(define y-ticks ((new.plot-y-ticks) y-min y-max))
|
||||
(define bounds-rect (vector (ivl x-min x-max) (ivl y-min y-max)))
|
||||
|
||||
(parameterize ([new.plot-title title]
|
||||
|
@ -117,9 +117,9 @@
|
|||
[#:lncolor lncolor (list/c byte? byte? byte?) '(255 0 0)]
|
||||
[#:out-file out-file (or/c path-string? output-port? #f) #f]
|
||||
) (is-a?/c image-snip%)
|
||||
(define x-ticks (new.default-x-ticks x-min x-max))
|
||||
(define y-ticks (new.default-y-ticks y-min y-max))
|
||||
(define z-ticks (new.default-z-ticks z-min z-max))
|
||||
(define x-ticks ((new.plot-x-ticks) x-min x-max))
|
||||
(define y-ticks ((new.plot-y-ticks) y-min y-max))
|
||||
(define z-ticks ((new.plot-z-ticks) z-min z-max))
|
||||
(define bounds-rect (vector (ivl x-min x-max) (ivl y-min y-max) (ivl z-min z-max)))
|
||||
|
||||
(parameterize ([new.plot-title title]
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
;; General plot parameters
|
||||
plot-x-axis? plot-y-axis? plot-z-axis?
|
||||
plot-x-far-axis? plot-y-far-axis? plot-z-far-axis?
|
||||
plot-x-max-ticks plot-y-max-ticks plot-z-max-ticks plot-d-max-ticks plot-r-max-ticks
|
||||
plot-x-far-max-ticks plot-y-far-max-ticks plot-z-far-max-ticks
|
||||
plot-width plot-height
|
||||
plot-foreground plot-foreground-alpha
|
||||
plot-background plot-background-alpha
|
||||
|
@ -68,14 +66,11 @@
|
|||
;; Functions
|
||||
pen-gap
|
||||
animated-samples
|
||||
default-x-ticks default-y-ticks default-z-ticks default-d-ticks default-r-ticks
|
||||
default-x-far-ticks default-y-far-ticks default-z-far-ticks
|
||||
default-contour-colors default-contour-fill-colors
|
||||
default-isosurface-colors default-isosurface-line-colors)
|
||||
;; Parameter groups
|
||||
plot-parameters
|
||||
plot-axes?
|
||||
plot-max-ticks
|
||||
plot-appearance
|
||||
plot3d-appearance
|
||||
plot-output
|
||||
|
|
|
@ -8,18 +8,19 @@
|
|||
(struct (tick pre-tick) ([value real?] [major? boolean?] [label string?]))
|
||||
(struct ticks ([layout ticks-layout/c] [format ticks-format/c])))
|
||||
24h-descending-date-ticks-formats 12h-descending-date-ticks-formats
|
||||
descending-time-ticks-formats
|
||||
24h-descending-time-ticks-formats 12h-descending-time-ticks-formats
|
||||
us-currency-scales uk-currency-scales eu-currency-scales
|
||||
us-currency-formats uk-currency-formats eu-currency-formats
|
||||
ticks-layout/c ticks-format/c
|
||||
(activate-contract-out ticks-mimic ticks-scale ticks-add linear-scale
|
||||
no-ticks-layout no-ticks
|
||||
no-ticks-layout no-ticks-format no-ticks
|
||||
(activate-contract-out ticks-default-number
|
||||
ticks-mimic ticks-scale ticks-add linear-scale
|
||||
linear-ticks-layout linear-ticks-format linear-ticks
|
||||
log-ticks-layout log-ticks-format log-ticks
|
||||
date-ticks-formats date-ticks-layout date-ticks-format date-ticks
|
||||
time-ticks-formats time-ticks-layout time-ticks-format time-ticks
|
||||
bit/byte-ticks-format bit/byte-ticks
|
||||
currency-ticks-scales currency-ticks-formats
|
||||
currency-ticks-layout currency-ticks-format currency-ticks
|
||||
currency-ticks-format currency-ticks
|
||||
fraction-ticks-format fraction-ticks
|
||||
collapse-ticks))
|
||||
|
|
|
@ -12,9 +12,7 @@
|
|||
(provide (struct-out ivl))
|
||||
|
||||
(require "contracted/axis-transform.rkt")
|
||||
(provide axis-transform-compose axis-transform-append axis-transform-bound
|
||||
id-transform log-transform cbrt-transform hand-drawn-transform
|
||||
stretch-transform collapse-transform)
|
||||
(provide (all-from-out "contracted/axis-transform.rkt"))
|
||||
|
||||
(require "contracted/ticks.rkt")
|
||||
(provide (all-from-out "contracted/ticks.rkt"))
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
(define r-min (if (and (<= x-min 0 x-max) (<= y-min 0 y-max)) 0 (apply min corner-rs)))
|
||||
(define r-max (apply max corner-rs))
|
||||
(define ts (filter (λ (t) (not (zero? (pre-tick-value t))))
|
||||
(default-r-ticks r-min r-max)))
|
||||
((plot-r-ticks) r-min r-max)))
|
||||
;; Draw the tick lines
|
||||
(for ([t (in-list ts)])
|
||||
(match-define (tick r major? label) t)
|
||||
|
|
|
@ -96,14 +96,12 @@
|
|||
(tick x #t (->plot-label cat)))])
|
||||
(if far-ticks? (values empty ticks) (values ticks empty))))
|
||||
(match-let*
|
||||
([(vector default-x-ticks default-y-ticks)
|
||||
(maybe-invert default-x-ticks default-y-ticks)]
|
||||
[(vector default-x-far-ticks default-y-far-ticks)
|
||||
(maybe-invert default-x-far-ticks default-y-far-ticks)]
|
||||
[(vector x-ticks y-ticks)
|
||||
(maybe-invert x-ticks (default-y-ticks y-min y-max))]
|
||||
[(vector x-far-ticks y-far-ticks)
|
||||
(maybe-invert x-far-ticks (default-y-far-ticks y-min y-max))])
|
||||
([(vector plot-x-ticks plot-y-ticks) (maybe-invert (plot-x-ticks)
|
||||
(plot-y-ticks))]
|
||||
[(vector plot-x-far-ticks plot-y-far-ticks) (maybe-invert (plot-x-far-ticks)
|
||||
(plot-y-far-ticks))]
|
||||
[(vector x-ticks y-ticks) (maybe-invert x-ticks (plot-y-ticks y-min y-max))]
|
||||
[(vector x-far-ticks y-far-ticks) (maybe-invert x-far-ticks (plot-y-far-ticks y-min y-max))])
|
||||
(values x-ticks x-far-ticks y-ticks y-far-ticks)))
|
||||
|
||||
(defproc (discrete-histogram
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
(if y-far-ticks? (values empty ts) (values ts empty))))
|
||||
(values x-ticks x-far-ticks
|
||||
y-ticks y-far-ticks
|
||||
(default-z-ticks z-min z-max) (default-z-far-ticks z-min z-max)))
|
||||
((plot-z-ticks) z-min z-max) ((plot-z-far-ticks) z-min z-max)))
|
||||
|
||||
(define (adjust/gap i gap)
|
||||
(match-define (ivl x1 x2) i)
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
@section{Convenience Contracts}
|
||||
|
||||
@doc-apply[contract/c]{
|
||||
Identifies @racket[contract?]s and predicates that can be used as contracts.
|
||||
}
|
||||
|
||||
@doc-apply[treeof]{
|
||||
Identifies trees of values that meet the contract @(racket ct).
|
||||
Used by @(racket plot) and @(racket plot3d) to construct the contract for a tree of @(racket renderer2d?) or @(racket renderer3d?).
|
||||
|
@ -49,6 +53,9 @@ A list containing the symbols that are valid @(racket points) symbols.
|
|||
|
||||
@section{Appearance Argument Sequence Contracts}
|
||||
|
||||
@doc-apply[maybe-function/c]{
|
||||
}
|
||||
|
||||
@doc-apply[plot-colors/c]{
|
||||
The contract for @(racket #:colors) arguments, as in @(racket contours).
|
||||
If the contracted value is a function, it is intended to take a list of values, such as contour values, as input, and return a list of colors.
|
||||
|
|
|
@ -4,8 +4,4 @@
|
|||
|
||||
@title[#:tag "custom"]{Making Custom Plot Renderers}
|
||||
|
||||
@defmodule[plot/custom]
|
||||
|
||||
Eventually, enough of the underlying PLoT API will be exposed that anyone can create new @tech{renderers}.
|
||||
However, the underlying API still changes too often.
|
||||
As soon as it settles, @racketmodname[plot/custom] will export it, and this page will document how to use it.
|
||||
@declare-exporting[plot/utils]
|
||||
|
|
|
@ -31,42 +31,6 @@ The quality of JPEG images written by @(racket plot-file) and @(racket plot3d-fi
|
|||
If @(racket #t), @(racket plot-file) and @(racket plot3d-file) open a dialog when writing PostScript or PDF files. See @(racket post-script-dc%) and @(racket pdf-dc%).
|
||||
}
|
||||
|
||||
@section{Axis Transforms}
|
||||
|
||||
@doc-apply[plot-x-transform]
|
||||
@doc-apply[plot-y-transform]
|
||||
@doc-apply[plot-z-transform]{
|
||||
Per-axis, nonlinear transforms. Set these, for example, to plot with log-scale axes. See @(racket log-transform).
|
||||
}
|
||||
|
||||
@doc-apply[id-transform]{
|
||||
The default transform for all axes.
|
||||
}
|
||||
|
||||
@doc-apply[log-transform]{
|
||||
A log transform. Use this to generate plots with log-scale axes. Any log-scaled axis must be on a positive interval.
|
||||
|
||||
@examples[#:eval plot-eval
|
||||
(parameterize ([plot-y-transform log-transform])
|
||||
(plot (function (λ (x) x) 0.01 1)))
|
||||
(parameterize ([plot-x-transform log-transform])
|
||||
(plot (function (λ (x) x) -1 1)))]
|
||||
}
|
||||
|
||||
@doc-apply[cbrt-transform]{
|
||||
A "cube-root" transform. Unlike the log transform, it is defined on the entire real line, making it better for testing the appearance of plots with nonlinearly transformed axes.
|
||||
}
|
||||
|
||||
@doc-apply[hand-drawn-transform]{
|
||||
An @italic{extremely important} test case, which makes sure that @(plot-name) can use any monotone, invertible function as an axis transform.
|
||||
|
||||
The @(racket freq) parameter controls the ``shakiness'' of the transform. At high values, it makes plots look like Peanuts cartoons. For example,
|
||||
|
||||
@interaction[#:eval plot-eval (parameterize ([plot-x-transform (hand-drawn-transform 200)]
|
||||
[plot-y-transform (hand-drawn-transform 200)])
|
||||
(plot (function sqr -1 1)))]
|
||||
}
|
||||
|
||||
@section{General Appearance}
|
||||
|
||||
@doc-apply[plot-foreground]
|
||||
|
@ -90,6 +54,9 @@ See @(racket ->pen-color) and @(racket ->brush-color) for details on how PLoT in
|
|||
@doc-apply[plot-y-label]
|
||||
@doc-apply[plot-z-label]{The title and axis labels. A @(racket #f) value means the label is not drawn and takes no space. A @(racket "") value effectively means the label is not drawn, but it takes space.
|
||||
}
|
||||
@doc-apply[plot-x-far-label]
|
||||
@doc-apply[plot-y-far-label]
|
||||
@doc-apply[plot-z-far-label]
|
||||
|
||||
@doc-apply[plot-animating?]{
|
||||
When @(racket #t), certain renderers draw simplified plots to speed up drawing. PLoT sets it to @(racket #t), for example, when a user is clicking and dragging a 3D plot to rotate it.
|
||||
|
@ -168,17 +135,33 @@ When @(racket #t), certain renderers draw simplified plots to speed up drawing.
|
|||
@doc-apply[rectangle3d-line-width]
|
||||
|
||||
@doc-apply[discrete-histogram-gap]
|
||||
@doc-apply[discrete-histogram-skip]
|
||||
@doc-apply[discrete-histogram-invert?]
|
||||
|
||||
@section{Decorations}
|
||||
|
||||
These parameters do not control the @italic{typical} appearance of plots. Instead, they control the look of renderers that add specific decorations, such as labeled points.
|
||||
|
||||
@doc-apply[x-axis-alpha]
|
||||
@doc-apply[y-axis-alpha]
|
||||
@doc-apply[z-axis-alpha]
|
||||
|
||||
@doc-apply[x-axis-far?]
|
||||
@doc-apply[y-axis-far?]
|
||||
@doc-apply[z-axis-far?]
|
||||
|
||||
@doc-apply[x-axis-ticks?]
|
||||
@doc-apply[y-axis-ticks?]
|
||||
@doc-apply[z-axis-ticks?]
|
||||
|
||||
@doc-apply[x-axis-labels?]
|
||||
@doc-apply[y-axis-labels?]
|
||||
@doc-apply[z-axis-labels?]
|
||||
|
||||
@doc-apply[polar-axes-number]
|
||||
@doc-apply[polar-axes-alpha]
|
||||
@doc-apply[polar-axes-ticks?]
|
||||
@doc-apply[polar-axes-labels?]
|
||||
|
||||
@doc-apply[label-anchor]
|
||||
@doc-apply[label-angle]
|
||||
|
@ -220,6 +203,7 @@ Single isosurfaces (@(racket isosurface3d)) use surface parameters. Nested isosu
|
|||
|
||||
@doc-apply[isosurface-levels]
|
||||
@doc-apply[isosurface-colors]
|
||||
@doc-apply[isosurface-styles]
|
||||
@doc-apply[isosurface-line-colors]
|
||||
@doc-apply[isosurface-line-widths]
|
||||
@doc-apply[isosurface-line-styles]
|
||||
|
|
|
@ -31,6 +31,8 @@ If you have code written for PLoT 5.1.3 or earlier, please see @secref["porting"
|
|||
|
||||
@include-section["renderer3d.scrbl"]
|
||||
|
||||
@include-section["ticks.scrbl"]
|
||||
|
||||
@include-section["utils.scrbl"]
|
||||
|
||||
@include-section["params.scrbl"]
|
||||
|
|
468
collects/plot/scribblings/ticks.scrbl
Normal file
468
collects/plot/scribblings/ticks.scrbl
Normal file
|
@ -0,0 +1,468 @@
|
|||
#lang scribble/manual
|
||||
|
||||
@(require "common.rkt" (for-label racket/date db))
|
||||
|
||||
@declare-exporting[plot]
|
||||
|
||||
@title[#:tag "ticks and transforms"]{Axis Transforms and Ticks}
|
||||
|
||||
@section[#:tag "transforms"]{Axis Transforms}
|
||||
|
||||
The @italic{x}, @italic{y} and @italic{z} axes for any plot can be independently transformed by parameterizing the plot on different @racket[plot-x-transform], @racket[plot-y-transform] and @racket[plot-z-transform] values.
|
||||
For example, to plot the @italic{x} axis with a log transform:
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform log-transform])
|
||||
(plot (function sin 1 100)))]
|
||||
Most @racket[log-transform]ed plots use different ticks than the default, uniformly spaced ticks, however.
|
||||
To put log ticks on the @italic{x} axis, set the @racket[plot-x-ticks] parameter:
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform log-transform]
|
||||
[plot-x-ticks (log-ticks)])
|
||||
(plot (function sin 1 100)))]
|
||||
See @secref["ticks"] for more details on parameterizing a plot's axis ticks.
|
||||
|
||||
@doc-apply[plot-x-transform]
|
||||
@doc-apply[plot-y-transform]
|
||||
@doc-apply[plot-z-transform]{
|
||||
Independent, per-axis, monotone, nonlinear transforms. PLoT comes with some typical (and some atypical) axis transforms, documented immediately below.
|
||||
}
|
||||
|
||||
@doc-apply[id-transform]{
|
||||
The identity axis transform, the default transform for all axes.
|
||||
}
|
||||
|
||||
@doc-apply[log-transform]{
|
||||
A log transform. Use this to generate plots with log-scale axes. Any such axis must have positive bounds.
|
||||
|
||||
The beginning of the @secref["ticks and transforms"] section has a working example. An example of exceeding the bounds is
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform log-transform])
|
||||
(plot (function (λ (x) x) -1 1)))]
|
||||
See @racket[axis-transform-bound] and @racket[axis-transform-append] for ways to get around an axis transform's bounds limitations.
|
||||
}
|
||||
|
||||
@doc-apply[stretch-transform]{
|
||||
Returns an axis transform that stretches a finite interval.
|
||||
|
||||
The following example uses a @racket[stretch-transform] to draw attention to the interval [-1,1] in an illustration of the limit of @italic{sin(x)/x} as @italic{x} approaches zero (a critical part of proving the derivative of @italic{sin(x)}):
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform (stretch-transform -1 1 20)]
|
||||
[plot-x-ticks (ticks-add (plot-x-ticks) '(-1 1))])
|
||||
(plot (list (y-axis -1 #:ticks? #f) (y-axis 1 #:ticks? #f)
|
||||
(function (λ (x) (/ (sin x) x)) -14 14
|
||||
#:width 2 #:color 4 #:label "y = sin(x)/x")
|
||||
(point-label (vector 0 1) "y → 1 as x → 0"
|
||||
#:anchor 'bottom-right))
|
||||
#:y-max 1.2))]
|
||||
}
|
||||
|
||||
@doc-apply[collapse-transform]{
|
||||
Returns an axis transform that collapses a finite interval to its midpoint.
|
||||
For example, to remove part of the long, boring asymptotic approach of @italic{atan(x)} toward π/2:
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform (collapse-transform 50 150)])
|
||||
(plot (function atan 10 200 #:label "y = atan(x)")
|
||||
#:legend-anchor 'center))]
|
||||
In this case, there were already ticks at the collapsed interval's endpoints.
|
||||
If there had not been, it would have been necessary to use @racket[ticks-add] to let viewers know precisely the interval that was collapsed.
|
||||
(See @racket[stretch-transform] for an example.)
|
||||
}
|
||||
|
||||
@doc-apply[cbrt-transform]{
|
||||
A ``cube-root'' transform, mostly used for testing.
|
||||
Unlike the log transform, it is defined on the entire real line, making it better for testing the appearance of plots with nonlinearly transformed axes.
|
||||
}
|
||||
|
||||
@doc-apply[hand-drawn-transform]{
|
||||
An @italic{extremely important} test case, which makes sure that @(plot-name) can use any monotone, invertible function as an axis transform.
|
||||
The @(racket freq) parameter controls the ``shakiness'' of the transform. At high values, it makes plots look like Peanuts cartoons.
|
||||
@examples[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform (hand-drawn-transform 200)]
|
||||
[plot-y-transform (hand-drawn-transform 200)])
|
||||
(plot (function sqr -1 1)))
|
||||
(parameterize ([plot-x-transform (hand-drawn-transform 50)]
|
||||
[plot-y-transform (hand-drawn-transform 50)]
|
||||
[plot-z-transform (hand-drawn-transform 50)])
|
||||
(plot3d (contour-intervals3d (λ (x y) (- (sqr x) (sqr y)))
|
||||
-1 1 -1 1 #:samples 9)))]
|
||||
|
||||
The last example shows that the transform is applied to the primitive shapes that comprise the plot (by recursive subdivision).
|
||||
}
|
||||
|
||||
@doc-apply[axis-transform/c]{
|
||||
The contract for axis transforms.
|
||||
|
||||
The easiest ways to construct novel axis transforms are to use the axis transform combinators @racket[axis-transform-append], @racket[axis-transform-bound] and @racket[axis-transform-compose], or to apply @racket[make-axis-transform] to an @racket[invertible-function].
|
||||
}
|
||||
|
||||
@doc-apply[axis-transform-append]{
|
||||
Returns an axis transform that transforms values less than @racket[mid] like @racket[t1], and transforms values greater than @racket[mid] like @racket[t2].
|
||||
(Whether it transforms @racket[mid] like @racket[t1] or @racket[t2] is immaterial, as a transformed @racket[mid] is equal to @racket[mid] either way.)
|
||||
@examples[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform (axis-transform-append
|
||||
(stretch-transform -2 -1 10)
|
||||
(stretch-transform 1 2 10)
|
||||
0)])
|
||||
(plot (function (λ (x) x) -3 3)))]
|
||||
}
|
||||
|
||||
@doc-apply[axis-transform-bound]{
|
||||
Returns an axis transform that transforms values like @racket[t] does in the interval [@racket[a],@racket[b]], but like the identity transform outside of it.
|
||||
For example, to bound @racket[log-transform] to an interval in which it is well-defined,
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform (axis-transform-bound
|
||||
log-transform 0.01 +inf.0)])
|
||||
(plot (function (λ (x) x) -4 8 #:label "y = x")))]
|
||||
}
|
||||
|
||||
@doc-apply[axis-transform-compose]{
|
||||
Composes two axis transforms.
|
||||
For example, to collapse part of a @racket[log-transform]ed axis, try something like
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-x-transform (axis-transform-compose
|
||||
log-transform
|
||||
(collapse-transform 2 4))])
|
||||
(plot (function (λ (x) x) 1 5)))]
|
||||
Argument order matters, but predicting the effects of exchanging arguments can be difficult.
|
||||
Fortunately, the effects are usually slight.
|
||||
}
|
||||
|
||||
@doc-apply[make-axis-transform]{
|
||||
Given a monotone @racket[invertible-function], returns an axis transform.
|
||||
Monotonicity is necessary, but cannot be enforced.
|
||||
The inverse is used to take samples uniformly along transformed axes (see @racket[nonlinear-seq]).
|
||||
|
||||
@examples[#:eval plot-eval
|
||||
(parameterize ([plot-y-transform (make-axis-transform
|
||||
(invertible-function sqrt sqr))])
|
||||
(plot (function (λ (x) x) 0 5)))]
|
||||
|
||||
An axis transform created by @racket[make-axis-transform] (or by any of the above combinators) does not transform the endpoints of an axis's bounds, to within floating-point error.
|
||||
For example,
|
||||
@interaction[#:eval plot-eval
|
||||
(match-let ([(invertible-function f g)
|
||||
(apply-axis-transform log-transform 1 3)])
|
||||
(values (list (f 1) (f 2) (f 3))
|
||||
(list (g 1) (g 2.2618595071429146) (g 3))))]
|
||||
|
||||
Technically, @racket[fun] does not need to be truly invertible.
|
||||
Given @racket[fun] = @racket[(invertible-function f g)], it is enough for @racket[f] to be a @hyperlink["http://en.wikipedia.org/wiki/Inverse_function#Left_and_right_inverses"]{left inverse} of @racket[g].
|
||||
If @racket[f] and @racket[g] had to be strict inverses of each other, there could be no @racket[collapse-transform].
|
||||
}
|
||||
|
||||
@doc-apply[apply-axis-transform]{
|
||||
Returns an invertible function that transforms axis points within the given axis bounds.
|
||||
This convenience function is used internally to transform points before rendering, but is provided for completeness.
|
||||
}
|
||||
|
||||
@section[#:tag "ticks"]{Axis Ticks}
|
||||
|
||||
Each plot axis has two indepedent sets of ticks: the @italic{near} ticks and the @italic{far} ticks.
|
||||
|
||||
@doc-apply[plot-x-ticks]
|
||||
@doc-apply[plot-x-far-ticks]
|
||||
@doc-apply[plot-y-ticks]
|
||||
@doc-apply[plot-y-far-ticks]
|
||||
@doc-apply[plot-z-ticks]
|
||||
@doc-apply[plot-z-far-ticks]{
|
||||
@examples[#:eval plot-eval
|
||||
(parameterize ([plot-x-label "Near x axis"]
|
||||
[plot-y-label "Near y axis"]
|
||||
[plot-z-label "Near z axis"]
|
||||
[plot-x-ticks (date-ticks)]
|
||||
[plot-y-ticks (time-ticks)]
|
||||
[plot-z-ticks (fraction-ticks)]
|
||||
[plot-x-far-label "Far x axis"]
|
||||
[plot-y-far-label "Far y axis"]
|
||||
[plot-z-far-label "Far z axis"]
|
||||
[plot-x-far-ticks (linear-ticks)]
|
||||
[plot-y-far-ticks (currency-ticks)]
|
||||
[plot-z-far-ticks (log-ticks #:base 2)])
|
||||
(plot3d (lines3d '(#(1 1 1) #(40000000 4 4)) #:style 'transparent)
|
||||
#:angle 45 #:altitude 50
|
||||
#:title "Axis Names and Tick Locations"))]
|
||||
At any @racket[#:angle], the far @italic{x} and @italic{y} ticks are behind the plot, and the far @italic{z} ticks are on the right.
|
||||
Far ticks are drawn, but not labeled, if they are identical to their corresponding near ticks.
|
||||
They are always identical by default.
|
||||
|
||||
@deftech{Major ticks} are longer than @deftech{minor ticks}. Major tick labels are always drawn unless collapsed with a nearby tick.
|
||||
Minor tick labels are never drawn.
|
||||
|
||||
Renderers produced by @racket[contours] and @racket[contour-intervals] use the value of @racket[plot-z-ticks] to place and label contour lines.
|
||||
For example, compare plots of the same function renderered using both @racket[contour-intervals] and @racket[contour-intervals3d]:
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize ([plot-z-ticks (currency-ticks)])
|
||||
(define (saddle x y) (- (sqr x) (sqr y)))
|
||||
(values
|
||||
(plot (contour-intervals saddle -1 1 -1 1 #:label "z")
|
||||
#:legend-anchor 'center)
|
||||
(plot3d (contour-intervals3d saddle -1 1 -1 1 #:label "z")
|
||||
#:legend-anchor 'center)))]
|
||||
}
|
||||
|
||||
@defstruct[ticks ([layout ticks-layout/c] [format ticks-format/c])]{
|
||||
A @racket[ticks] for a near or far axis consists of a @racket[layout] function, which determines the number of ticks and where they will be placed, and a @racket[format] function, which determines the ticks' labels.
|
||||
}
|
||||
|
||||
@doc-apply[ticks-default-number]{
|
||||
Most tick layout functions (and thus their corresponding @racket[ticks]-constructing functions) have a @racket[#:number] keyword argument with default @racket[(ticks-default-number)]. What the number means depends on the tick layout function. Most use it for the maximum number of major ticks.
|
||||
|
||||
It is unlikely to mean the exact number of major ticks.
|
||||
Without adjusting the number of ticks, layout functions usually cannot find uniformly spaced ticks that will have simple labels after formatting.
|
||||
For example, the following plot shows the actual number of major ticks for the interval [0,@italic{x}] when the requested number of ticks is 8, as generated by @racket[linear-ticks-layout]:
|
||||
@interaction[#:eval plot-eval
|
||||
(plot (function (λ (x)
|
||||
(count pre-tick-major?
|
||||
((linear-ticks-layout #:number 8) 0 x)))
|
||||
0.1 10)
|
||||
#:x-label "Interval [0,x]" #:y-label "Number of ticks")]
|
||||
}
|
||||
|
||||
@subsection{Linear Ticks}
|
||||
|
||||
@doc-apply[linear-ticks-layout]
|
||||
@doc-apply[linear-ticks-format]
|
||||
@doc-apply[linear-ticks]{
|
||||
The layout function, format function, and combined @racket[ticks] for uniformly spaced ticks.
|
||||
|
||||
To lay out ticks, @racket[linear-ticks-layout] finds the power of @racket[base] closest to the axis interval size, chooses a simple first tick, and then chooses a skip length using @racket[divisors] that maximizes the number of ticks without exceeding @racket[number].
|
||||
@margin-note*{For strategic use of non-default arguments, see @racket[bit/byte-ticks], @racket[currency-ticks], and @racket[fraction-ticks].}
|
||||
The default arguments correspond to the standard 1-2-5-in-base-10 rule used almost everywhere in plot tick layout.
|
||||
|
||||
To format ticks, @racket[linear-ticks-format] uses @racket[real->plot-label], and uses @racket[digits-for-range] to determine the maximum number of fractional digits in the decimal expansion.
|
||||
}
|
||||
|
||||
@subsection{Log Ticks}
|
||||
|
||||
@doc-apply[log-ticks-layout]
|
||||
@doc-apply[log-ticks-format]
|
||||
@doc-apply[log-ticks]{
|
||||
The layout function, format function, and combined @racket[ticks] for exponentially spaced major ticks.
|
||||
(The minor ticks between are uniformly spaced.)
|
||||
Use these ticks for @racket[log-transform]ed axes, because when exponentially spaced tick positions are @racket[log-transform]ed, they become uniformly spaced.
|
||||
|
||||
The @racket[#:base] keyword argument is the logarithm base.
|
||||
See @racket[plot-z-far-ticks] for an example of use.
|
||||
}
|
||||
|
||||
@subsection{Date Ticks}
|
||||
|
||||
@doc-apply[date-ticks-layout]
|
||||
@doc-apply[date-ticks-format]
|
||||
@doc-apply[date-ticks]{
|
||||
The layout function, format function, and combined @racket[ticks] for uniformly spaced ticks with date labels.
|
||||
|
||||
These axis ticks regard values as being in seconds since @italic{a system-dependent Universal Coordinated Time (UTC) epoch}.
|
||||
(For example, the Unix and Mac OS X epoch is January 1, 1970 UTC, and the Windows epoch is January 1, 1601 UTC.)
|
||||
Use @racket[date->seconds] to convert local dates to seconds, or @racket[datetime->real] to convert dates to UTC seconds in a way that accounts for time zone offsets.
|
||||
|
||||
Actually, @racket[date-ticks-layout] does not always space ticks @italic{quite} uniformly.
|
||||
For example, it rounds ticks that are spaced about one month apart or more to the nearest month.
|
||||
Generally, @racket[date-ticks-layout] tries to place ticks at minute, hour, day, week, month and year boundaries, as well as common multiples such as 90 days or 6 months.
|
||||
|
||||
To avoid displaying overlapping labels, @racket[date-ticks-format] chooses date formats from @racket[formats] for which labels will contain no redundant information.
|
||||
|
||||
All the format specifiers given in @racketmodname[srfi/19] (which are derived from Unix's @tt{date} command), except those that represent time zones, are allowed in date format strings.
|
||||
}
|
||||
|
||||
@doc-apply[date-ticks-formats]{
|
||||
The default date formats.
|
||||
}
|
||||
|
||||
@doc-apply[24h-descending-date-ticks-formats]
|
||||
@doc-apply[12h-descending-date-ticks-formats]
|
||||
|
||||
@subsection{Time Ticks}
|
||||
|
||||
@doc-apply[time-ticks-layout]
|
||||
@doc-apply[time-ticks-format]
|
||||
@doc-apply[time-ticks]{
|
||||
The layout function, format function, and combined @racket[ticks] for uniformly spaced ticks with time labels.
|
||||
|
||||
These axis ticks regard values as being in seconds.
|
||||
Use @racket[datetime->real] to convert @racket[sql-time] or @racket[plot-time] values to seconds.
|
||||
|
||||
Generally, @racket[time-ticks-layout] tries to place ticks at minute, hour and day boundaries, as well as common multiples such as 12 hours or 30 days.
|
||||
|
||||
To avoid displaying overlapping labels, @racket[time-ticks-format] chooses a date format from @racket[formats] for which labels will contain no redundant information.
|
||||
|
||||
All the time-related format specifiers given in @racketmodname[srfi/19] (which are derived from Unix's @tt{date} command) are allowed in time format strings.
|
||||
}
|
||||
|
||||
@doc-apply[time-ticks-formats]{
|
||||
The default time formats.
|
||||
}
|
||||
|
||||
@doc-apply[24h-descending-time-ticks-formats]
|
||||
@doc-apply[12h-descending-time-ticks-formats]
|
||||
|
||||
@subsection{Currency Ticks}
|
||||
|
||||
@doc-apply[currency-ticks-format]
|
||||
@doc-apply[currency-ticks]{
|
||||
The format function and combined @racket[ticks] for uniformly spaced ticks with currency labels.
|
||||
|
||||
The @racket[#:kind] keyword argument is either a string containing the currency symbol, or a currency code such as @racket['USD], @racket['GBP] or @racket['EUR].
|
||||
The @racket[currency-ticks-format] function can map most ISO 4217 currency codes to their corresponding currency symbol.
|
||||
|
||||
The @racket[#:scales] keyword argument is a list of suffixes for each 10@superscript{3} scale, such as @racket["K"] (US thousand, or kilo), @racket["bn"] (UK short-scale billion) or @racket["Md"] (EU long-scale milliard). Off-scale amounts are given power-of-ten suffixes such as ``×10@superscript{21}.''
|
||||
|
||||
The @racket[#:formats] keyword argument is a list of three format strings, representing the formats of positive, negative, and zero amounts, respectively. The format specifiers are:
|
||||
@itemlist[@item{@racket["~$"]: replaced by the currency symbol}
|
||||
@item{@racket["~w"]: replaced by the whole part of the amount}
|
||||
@item{@racket["~f"]: replaced by the fractional part, with 2 or more decimal digits}
|
||||
@item{@racket["~s"]: replaced by the scale suffix}
|
||||
@item{@racket["~~"]: replaced by ``~''}]
|
||||
|
||||
Note that the @racket[#:divisors] passed to @racket[linear-ticks-layout] are @racket['(1 2 4 5)]. This allows quarter divisions to be used for tick positions, corresponding to 25/100 denominations such as the US quarter dollar.
|
||||
}
|
||||
|
||||
@doc-apply[currency-ticks-scales]
|
||||
@doc-apply[currency-ticks-formats]{
|
||||
The default currency scales and formats.
|
||||
|
||||
For example, a PLoT user in France would probably begin programs with
|
||||
@racketblock[(require plot)
|
||||
(currency-ticks-scales eu-currency-scales)
|
||||
(currency-ticks-formats eu-currency-formats)]
|
||||
and use @racket[(currency-ticks #:kind 'EUR)] for local currency or @racket[(currency-ticks #:kind 'JPY)] for Japanese Yen.
|
||||
|
||||
Cultural sensitivity notwithstanding, when writing for a local audience, it is generally considered proper to use local currency scales and formats for foreign currencies.
|
||||
}
|
||||
|
||||
@doc-apply[us-currency-scales]{
|
||||
Short-scale suffix abbreviations as commonly used in the United States, Canada, and some other English-speaking countries. These stand for ``kilo,'' ``million,'' ``billion,'' and ``trillion.''
|
||||
}
|
||||
|
||||
@doc-apply[uk-currency-scales]{
|
||||
Short-scale suffix abbreviations as commonly used in the United Kingdom since switching to the short scale in 1974, and as currently recommended by the Daily Telegraph and Times style guides.
|
||||
}
|
||||
|
||||
@doc-apply[eu-currency-scales]{
|
||||
European Union long-scale suffix abbreviations, which stand for ``kilo,'' ``million,'' ``milliard,'' and ``billion.''
|
||||
|
||||
The abbreviations actually used vary with geography, even within countries, but these seem to be common.
|
||||
Further long-scale suffix abbreviations such as for ``billiard'' are ommitted due to lack of even weak consensus.
|
||||
}
|
||||
|
||||
@doc-apply[us-currency-formats]{
|
||||
Common currency formats used in the United States.
|
||||
}
|
||||
|
||||
@doc-apply[uk-currency-formats]{
|
||||
Common currency formats used in the United Kingdom.
|
||||
Note that it sensibly uses a negative sign to denote negative amounts.
|
||||
}
|
||||
|
||||
@doc-apply[eu-currency-formats]{
|
||||
A guess at common currency formats for the European Union.
|
||||
Like scale suffixes, actual formats vary with geography, but currency formats can even vary with audience or tone.
|
||||
}
|
||||
|
||||
@subsection{Other Ticks}
|
||||
|
||||
@doc-apply[no-ticks-layout]
|
||||
@doc-apply[no-ticks-format]
|
||||
@doc-apply[no-ticks]{
|
||||
The layout function, format function, and combined @racket[ticks] for no ticks whatsoever.
|
||||
@examples[#:eval plot-eval
|
||||
(parameterize ([plot-x-ticks no-ticks]
|
||||
[plot-y-ticks no-ticks]
|
||||
[plot-x-label #f]
|
||||
[plot-y-label #f])
|
||||
(plot (list (polar-axes) (polar (λ (θ) 1/3)))))]
|
||||
}
|
||||
|
||||
@doc-apply[bit/byte-ticks-format]
|
||||
@doc-apply[bit/byte-ticks]{
|
||||
The format function and and combined @racket[ticks] for bit or byte values.
|
||||
|
||||
The @racket[#:kind] keyword argument indicates either International System of Units (@racket['SI]) suffixes, as used to communicate hard drive capacities, or Computer Science (@racket['CS]) suffixes, as used to communicate memory capacities.
|
||||
}
|
||||
|
||||
@doc-apply[fraction-ticks-format]
|
||||
@doc-apply[fraction-ticks]{
|
||||
The format function and and combined @racket[ticks] for fraction-formatted values.
|
||||
}
|
||||
|
||||
@subsection{Tick Combinators}
|
||||
|
||||
@doc-apply[ticks-mimic]{
|
||||
Returns a @racket[ticks] that mimics the given @racket[ticks] returned by @racket[thunk].
|
||||
Used in default values for @racket[plot-x-far-ticks], @racket[plot-y-far-ticks] and @racket[plot-z-far-ticks] to ensure that, unless one of these parameters is changed, the far tick labels are not drawn.
|
||||
}
|
||||
|
||||
@doc-apply[ticks-add]{
|
||||
Returns a new @racket[ticks] that acts like @racket[t], except that it puts additional ticks at positions @racket[xs]. If @racket[major?] is true, the ticks at positions @racket[xs] are all @tech{major ticks}; otherwise, they are minor ticks.
|
||||
}
|
||||
|
||||
@doc-apply[ticks-scale]{
|
||||
Returns a new @racket[ticks] that acts like @racket[t], but for an axis transformed by @racket[fun].
|
||||
Unlike with typical @secref["transforms"], @racket[fun] is allowed to transform axis endpoints.
|
||||
(See @racket[make-axis-transform] for an explanation about transforming endpoints.)
|
||||
|
||||
Use @racket[ticks-scale] to plot values at multiple scales simultaneously, with one scale on the near axis and one scale on the far axis.
|
||||
The following example plots degrees Celsius on the left and degrees Farenheit on the right:
|
||||
@interaction[#:eval plot-eval
|
||||
(parameterize
|
||||
([plot-x-ticks (time-ticks)]
|
||||
[plot-y-far-ticks (ticks-scale (plot-y-ticks)
|
||||
(linear-scale 9/5 32))]
|
||||
[plot-y-label "Temperature (\u00b0C)"]
|
||||
[plot-y-far-label "Temperature (\u00b0F)"])
|
||||
(define data
|
||||
(list #(0 0) #(15 0.6) #(30 9.5) #(45 10.0) #(60 16.6)
|
||||
#(75 41.6) #(90 42.7) #(105 65.5) #(120 78.9)
|
||||
#(135 78.9) #(150 131.1) #(165 151.1) #(180 176.2)))
|
||||
(plot (list
|
||||
(function (λ (x) (/ (sqr x) 180)) 0 180
|
||||
#:style 'long-dash #:color 3 #:label "Trend")
|
||||
(lines data #:color 2 #:width 2)
|
||||
(points data #:color 1 #:line-width 2 #:label "Measured"))
|
||||
#:y-min -25 #:x-label "Time"))]
|
||||
}
|
||||
|
||||
@subsection{Tick Data Types and Contracts}
|
||||
|
||||
@defstruct[pre-tick ([value real?] [major? boolean?])]{
|
||||
Represents a tick that has not yet been labeled.
|
||||
}
|
||||
@defstruct[(tick pre-tick) ([label string?])]{
|
||||
Represents a tick with a label.
|
||||
}
|
||||
|
||||
@doc-apply[ticks-layout/c]{
|
||||
The contract for tick layout functions. Note that a layout function returns @racket[pre-tick]s, or unlabeled ticks.
|
||||
}
|
||||
|
||||
@doc-apply[ticks-format/c]{
|
||||
The contract for tick format functions. A format function receives axis bounds so it can determine how many decimal digits to display (usually by applying @racket[digits-for-range] to the bounds).
|
||||
}
|
||||
|
||||
@section[#:tag "invertible"]{Invertible Functions}
|
||||
|
||||
@defstruct[invertible-function ([f (real? . -> . real?)] [g (real? . -> . real?)])]{
|
||||
Represents an invertible function. Used for @secref["transforms"] and by @racket[ticks-scale].
|
||||
|
||||
The function itself is @racket[f], and its inverse is @racket[g].
|
||||
Because @racket[real?]s can be inexact, this invariant must be approximate and therefore cannot be enforced.
|
||||
(For example, @racket[(exp (log 10))] = @racket[10.000000000000002].)
|
||||
The obligation to maintain it rests on whomever constructs one.
|
||||
}
|
||||
|
||||
@doc-apply[id-function]{
|
||||
The identity function as an @racket[invertible-function].
|
||||
}
|
||||
|
||||
@doc-apply[invertible-compose]{
|
||||
Returns the composition of two invertible functions.
|
||||
}
|
||||
|
||||
@doc-apply[invertible-inverse]{
|
||||
Returns the inverse of an invertible function.
|
||||
}
|
||||
|
||||
@doc-apply[linear-scale]{
|
||||
Returns a one-dimensional linear scaling function, as an @racket[invertible-function].
|
||||
This function constructs the most common arguments to @racket[ticks-scale].
|
||||
}
|
|
@ -6,13 +6,7 @@
|
|||
|
||||
@defmodule[plot/utils]
|
||||
|
||||
@doc-apply[degrees->radians]{
|
||||
Converts degrees to radians.
|
||||
}
|
||||
|
||||
@doc-apply[radians->degrees]{
|
||||
Converts radians to degrees.
|
||||
}
|
||||
@section{Formatting}
|
||||
|
||||
@doc-apply[digits-for-range]{
|
||||
Given a range, returns the number of decimal places necessary to distinguish numbers in the range. This may return negative numbers for large ranges.
|
||||
|
@ -41,37 +35,7 @@ Converts a Racket value to a label. Used by @(racket discrete-histogram) and @(r
|
|||
Like @(racket real->decimal-string), but removes trailing zeros and a trailing decimal point.
|
||||
}
|
||||
|
||||
@doc-apply[linear-seq]{
|
||||
Returns a list of evenly spaced real numbers between @(racket start) and @(racket end).
|
||||
If @(racket start?) is @(racket #t), the list includes @(racket start).
|
||||
If @(racket end?) is @(racket #t), the list includes @(racket end).
|
||||
|
||||
This function is used internally to generate sample points.
|
||||
|
||||
@examples[#:eval plot-eval
|
||||
(linear-seq 0 1 5)
|
||||
(linear-seq 0 1 5 #:start? #f)
|
||||
(linear-seq 0 1 5 #:end? #f)
|
||||
(linear-seq 0 1 5 #:start? #f #:end? #f)]
|
||||
}
|
||||
|
||||
@doc-apply[linear-seq*]{
|
||||
Like @(racket linear-seq), but accepts a list of reals instead of a start and end.
|
||||
The @(racket #:start?) and @(racket #:end?) keyword arguments work as in @(racket linear-seq).
|
||||
This function does not guarantee that each inner value will be in the returned list.
|
||||
|
||||
@examples[#:eval plot-eval
|
||||
(linear-seq* '(0 1 2) 5)
|
||||
(linear-seq* '(0 1 2) 6)
|
||||
(linear-seq* '(0 1 0) 5)]
|
||||
}
|
||||
|
||||
@doc-apply[bounds->intervals]{
|
||||
Given a list of points, returns intervals between each pair.
|
||||
|
||||
Use this to construct inputs for @(racket rectangles) and @(racket rectangles3d).
|
||||
@examples[#:eval plot-eval (bounds->intervals (linear-seq 0 1 5))]
|
||||
}
|
||||
@section{Plot Colors and Styles}
|
||||
|
||||
@doc-apply[color-seq]{
|
||||
Interpolates between colors---red, green and blue components separately---using @(racket linear-seq).
|
||||
|
@ -169,18 +133,44 @@ Integer brush styles repeat starting at @(racket 7).
|
|||
(map ->brush-style '(4 5 6))]
|
||||
}
|
||||
|
||||
@defstruct[invertible-function ([f (real? . -> . real?)] [finv (real? . -> . real?)])]{
|
||||
Represents an invertible function.
|
||||
@section{Plot-Specific Math}
|
||||
|
||||
The function itself is @(racket f), and its inverse is @(racket finv).
|
||||
Because @(racket real?)s can be inexact, this invariant must be approximate and therefore cannot be enforced.
|
||||
(For example, @(racket (exp (log 10))) = @(racket 10.000000000000002).)
|
||||
The obligation to maintain it rests on whomever constructs one.
|
||||
@subsection{Real Numbers}
|
||||
|
||||
An axis transform such as @(racket plot-x-transform) is a function from bounds @(racket start end) to an @(racket invertible-function) for which @(racket (f start)) = @(racket start) and @(racket (f end)) = @(racket end) (approximately), and the same is true of @(racket finv).
|
||||
The function @(racket f) is used to transform points before drawing; its inverse @(racket finv) is used to generate samples that will be evenly spaced after being transformed by @(racket f).
|
||||
@doc-apply[regular-real?]{
|
||||
}
|
||||
|
||||
(Technically, because of the way PLoT uses @(racket invertible-function), @(racket f) must only be a left inverse of @(racket finv); there is no requirement that @(racket f) also be a right inverse of @(racket finv).)
|
||||
@doc-apply[degrees->radians]{
|
||||
Converts degrees to radians.
|
||||
}
|
||||
|
||||
@doc-apply[radians->degrees]{
|
||||
Converts radians to degrees.
|
||||
}
|
||||
|
||||
@doc-apply[linear-seq]{
|
||||
Returns a list of evenly spaced real numbers between @(racket start) and @(racket end).
|
||||
If @(racket start?) is @(racket #t), the list includes @(racket start).
|
||||
If @(racket end?) is @(racket #t), the list includes @(racket end).
|
||||
|
||||
This function is used internally to generate sample points.
|
||||
|
||||
@examples[#:eval plot-eval
|
||||
(linear-seq 0 1 5)
|
||||
(linear-seq 0 1 5 #:start? #f)
|
||||
(linear-seq 0 1 5 #:end? #f)
|
||||
(linear-seq 0 1 5 #:start? #f #:end? #f)]
|
||||
}
|
||||
|
||||
@doc-apply[linear-seq*]{
|
||||
Like @(racket linear-seq), but accepts a list of reals instead of a start and end.
|
||||
The @(racket #:start?) and @(racket #:end?) keyword arguments work as in @(racket linear-seq).
|
||||
This function does not guarantee that each inner value will be in the returned list.
|
||||
|
||||
@examples[#:eval plot-eval
|
||||
(linear-seq* '(0 1 2) 5)
|
||||
(linear-seq* '(0 1 2) 6)
|
||||
(linear-seq* '(0 1 0) 5)]
|
||||
}
|
||||
|
||||
@doc-apply[nonlinear-seq]{
|
||||
|
@ -193,6 +183,23 @@ This is used to generate samples for transformed axes.
|
|||
(plot (area-histogram sqr (nonlinear-seq 1 10 4 log-transform))))]
|
||||
}
|
||||
|
||||
@subsection[#:tag "math.vectors"]{Vectors}
|
||||
|
||||
@subsection[#:tag "math.intervals"]{Intervals}
|
||||
|
||||
@doc-apply[bounds->intervals]{
|
||||
Given a list of points, returns intervals between each pair.
|
||||
|
||||
Use this to construct inputs for @(racket rectangles) and @(racket rectangles3d).
|
||||
@examples[#:eval plot-eval (bounds->intervals (linear-seq 0 1 5))]
|
||||
}
|
||||
|
||||
@subsection[#:tag "math.rectangles"]{Rectangles}
|
||||
|
||||
@section{Dates and Times}
|
||||
|
||||
@section{Sampling}
|
||||
|
||||
@defstruct[mapped-function ([f (any/c . -> . any/c)] [fmap ((listof any/c) . -> . (listof any/c))])]{
|
||||
Represents a function that maps over lists differently than @(racket (map f xs)).
|
||||
|
||||
|
@ -201,6 +208,8 @@ With some functions, mapping over a list can be done much more quickly if done s
|
|||
Renderer-producing functions that accept a @(racket (real? . -> . real?)) also accept a @(racket mapped-function), and use its @(racket fmap) to sample more efficiently.
|
||||
}
|
||||
|
||||
@section{Denity Estimation}
|
||||
|
||||
@doc-apply[kde]{
|
||||
Given samples and a kernel bandwidth, returns a @(racket mapped-function) representing a kernel density estimate, and bounds, outside of which the density estimate is zero. Used by @(racket density).
|
||||
}
|
||||
|
|
|
@ -18,11 +18,10 @@
|
|||
|
||||
(time (plot (function values 0 1000)))
|
||||
|
||||
(parameterize ([plot-x-ticks (log-ticks #:base 4)]
|
||||
[plot-x-transform log-transform]
|
||||
[plot-y-max-ticks 10]
|
||||
[plot-y-ticks (linear-ticks)]
|
||||
[plot-y-transform log-transform])
|
||||
(parameterize ([plot-x-transform log-transform]
|
||||
[plot-x-ticks (log-ticks #:base 4)]
|
||||
[plot-y-transform log-transform]
|
||||
[plot-y-ticks (linear-ticks #:number 10)])
|
||||
(plot (function values 1 243)))
|
||||
|
||||
(parameterize ([plot-background "black"]
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
(plot-font-family 'swiss)
|
||||
|
||||
(plot (function (λ (x) (count pre-tick-major? ((linear-ticks) 0 x 8)))
|
||||
(plot (function (λ (x) (count pre-tick-major? ((linear-ticks #:number 8) 0 x)))
|
||||
0.1 10))
|
||||
|
||||
(plot (function (λ (x) (count pre-tick-major? ((linear-ticks) 0 x 40)))
|
||||
(plot (function (λ (x) (count pre-tick-major? ((linear-ticks #:number 40) 0 x)))
|
||||
1 100))
|
||||
|
||||
(parameterize ([plot-x-ticks (linear-ticks #:base 2 #:divisors '(1 2))]
|
||||
|
@ -20,8 +20,7 @@
|
|||
[plot-y-ticks (fraction-ticks)])
|
||||
(plot (function (λ (x) (+ 1 (cos x))) 0.0001 12)))
|
||||
|
||||
(parameterize ([plot-x-ticks (date-ticks)]
|
||||
[plot-x-max-ticks 3]
|
||||
(parameterize ([plot-x-ticks (date-ticks #:number 3)]
|
||||
[plot-y-ticks (currency-ticks)])
|
||||
(plot (function values -1 1)))
|
||||
|
||||
|
@ -40,7 +39,7 @@
|
|||
#:x-label "Euros"
|
||||
#:y-label "Dollars"))
|
||||
|
||||
(parameterize ([plot-x-ticks (no-ticks)])
|
||||
(parameterize ([plot-x-ticks no-ticks])
|
||||
(plot (function sin -1 4)))
|
||||
|
||||
(parameterize ([plot-x-transform log-transform]
|
||||
|
@ -90,7 +89,8 @@
|
|||
(parameterize ([plot-y-ticks (ticks-scale (log-ticks) exp-scale)])
|
||||
(plot (function values -10 10)))
|
||||
|
||||
(parameterize ([plot-y-ticks (ticks-add (no-ticks) '(1/3 2/3))])
|
||||
(parameterize ([plot-y-ticks (ticks-add (ticks no-ticks-layout (linear-ticks-format))
|
||||
'(1/3 2/3))])
|
||||
(plot (function sin -4 4)))
|
||||
|
||||
(plot (list (function sin -4 4)
|
||||
|
@ -98,7 +98,7 @@
|
|||
(x-ticks (list (tick 1.5 #t "3/2") (tick 3 #t "Three")))
|
||||
(y-ticks (list (tick 1/4 #t "1/4") (tick -1/4 #f "")))))
|
||||
|
||||
(parameterize ([plot-z-max-ticks 5])
|
||||
(parameterize ([plot-z-ticks (linear-ticks #:number 5)])
|
||||
(plot3d (list (surface3d (λ (x y) (* 2 (+ (sin x) (cos y)))) -4 4 -4 4 #:alpha 1/2)
|
||||
(x-ticks (list (tick 1.5 #t "3/2") (tick 3 #t "Three")))
|
||||
(y-ticks (list (tick 1/3 #t "1/3") (tick -1/3 #f "1/3")))
|
||||
|
@ -127,13 +127,12 @@
|
|||
(plot (function sin (- pi) pi)))
|
||||
|
||||
(parameterize ([plot-x-far-label "x far axis"]
|
||||
[plot-x-max-ticks 10]
|
||||
[plot-x-ticks (linear-ticks #:number 10)]
|
||||
[plot-y-far-label "y far axis"]
|
||||
[plot-y-far-ticks (date-ticks)]
|
||||
[plot-z-label "z axis"]
|
||||
[plot-z-far-label "z far axis"]
|
||||
[plot-z-far-ticks (currency-ticks)]
|
||||
[plot-z-far-max-ticks 5])
|
||||
[plot-z-far-ticks (currency-ticks #:number 5)])
|
||||
(plot3d (surface3d (λ (x y) (+ (sin x) (cos y))) -2 2 -2 2 #:alpha 1/2)
|
||||
#:angle 60 #:altitude 35))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user