
I also made some minor changes to `plot' so that its functions would type more easily. In particular, everything that used to take a list of vectors now accepts a (Sequenceof (Sequenceof Real)). The 3D discrete histogram renderers now also accept lists as well as vectors in the sequence of categories. For now, in typed/plot functions, optional non-keyword arguments are required. As soon as Vincent closes PR 13354, I should be able to uncomment part of a macro in "typed/plot/syntax.rkt" to make them correctly optional.
165 lines
7.9 KiB
Racket
165 lines
7.9 KiB
Racket
#lang racket/base
|
|
|
|
;; Line renderers.
|
|
|
|
(require racket/contract racket/class racket/match racket/math racket/list racket/sequence
|
|
unstable/latent-contract/defthing
|
|
unstable/contract
|
|
plot/utils
|
|
"../common/utils.rkt")
|
|
|
|
(provide (all-defined-out))
|
|
|
|
;; ===================================================================================================
|
|
;; Lines, parametric, polar
|
|
|
|
(define ((lines-render-proc vs color width style alpha label) area)
|
|
(send area put-alpha alpha)
|
|
(send area put-pen color width style)
|
|
(send area put-lines vs)
|
|
|
|
(cond [label (line-legend-entry label color width style)]
|
|
[else empty]))
|
|
|
|
(defproc (lines [vs (sequence/c (sequence/c real?))]
|
|
[#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
|
|
[#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
|
|
[#:color color plot-color/c (line-color)]
|
|
[#:width width (>=/c 0) (line-width)]
|
|
[#:style style plot-pen-style/c (line-style)]
|
|
[#:alpha alpha (real-in 0 1) (line-alpha)]
|
|
[#:label label (or/c string? #f) #f]
|
|
) renderer2d?
|
|
(let ([vs (sequence->listof-vector 'lines vs 2)])
|
|
(define rvs (filter vrational? vs))
|
|
(cond [(empty? rvs) (renderer2d #f #f #f #f)]
|
|
[else
|
|
(match-define (list (vector rxs rys) ...) rvs)
|
|
(let ([x-min (if x-min x-min (apply min* rxs))]
|
|
[x-max (if x-max x-max (apply max* rxs))]
|
|
[y-min (if y-min y-min (apply min* rys))]
|
|
[y-max (if y-max y-max (apply max* rys))])
|
|
(renderer2d (vector (ivl x-min x-max) (ivl y-min y-max)) #f default-ticks-fun
|
|
(lines-render-proc vs color width style alpha label)))])))
|
|
|
|
(defproc (parametric [f (real? . -> . (sequence/c real?))]
|
|
[t-min rational?] [t-max rational?]
|
|
[#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
|
|
[#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
|
|
[#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
|
|
[#:color color plot-color/c (line-color)]
|
|
[#:width width (>=/c 0) (line-width)]
|
|
[#:style style plot-pen-style/c (line-style)]
|
|
[#:alpha alpha (real-in 0 1) (line-alpha)]
|
|
[#:label label (or/c string? #f) #f]
|
|
) renderer2d?
|
|
(let ([f (λ (t) (sequence-head-vector 'parametric (f t) 2))])
|
|
(lines (map f (linear-seq t-min t-max samples))
|
|
#:x-min x-min #:x-max x-max #:y-min y-min #:y-max y-max
|
|
#:color color #:width width #:style style #:alpha alpha
|
|
#:label label)))
|
|
|
|
(defproc (polar [f (real? . -> . real?)]
|
|
[θ-min real? 0] [θ-max real? (* 2 pi)]
|
|
[#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
|
|
[#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
|
|
[#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
|
|
[#:color color plot-color/c (line-color)]
|
|
[#:width width (>=/c 0) (line-width)]
|
|
[#:style style plot-pen-style/c (line-style)]
|
|
[#:alpha alpha (real-in 0 1) (line-alpha)]
|
|
[#:label label (or/c string? #f) #f]
|
|
) renderer2d?
|
|
(lines (let ([θs (linear-seq θ-min θ-max samples)])
|
|
(map polar->cartesian θs (map* f θs)))
|
|
#:x-min x-min #:x-max x-max #:y-min y-min #:y-max y-max
|
|
#:color color #:width width #:style style #:alpha alpha
|
|
#:label label))
|
|
|
|
;; ===================================================================================================
|
|
;; Function
|
|
|
|
(define ((function-render-proc f samples color width style alpha label) area)
|
|
(match-define (vector x-ivl y-ivl) (send area get-bounds-rect))
|
|
(match-define (sample xs ys y-min y-max) (f x-ivl samples))
|
|
|
|
(send area put-alpha alpha)
|
|
(send area put-pen color width style)
|
|
(send area put-lines (map vector xs ys))
|
|
|
|
(cond [label (line-legend-entry label color width style)]
|
|
[else empty]))
|
|
|
|
(defproc (function [f (real? . -> . real?)]
|
|
[x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
|
|
[#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
|
|
[#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
|
|
[#:color color plot-color/c (line-color)]
|
|
[#:width width (>=/c 0) (line-width)]
|
|
[#:style style plot-pen-style/c (line-style)]
|
|
[#:alpha alpha (real-in 0 1) (line-alpha)]
|
|
[#:label label (or/c string? #f) #f]
|
|
) renderer2d?
|
|
(define x-ivl (ivl x-min x-max))
|
|
(define y-ivl (ivl y-min y-max))
|
|
(let ([f (function->sampler f x-ivl)])
|
|
(renderer2d (vector x-ivl y-ivl)
|
|
(function-bounds-fun f samples)
|
|
default-ticks-fun
|
|
(function-render-proc f samples color width style alpha label))))
|
|
|
|
;; ===================================================================================================
|
|
;; Inverse function
|
|
|
|
(define ((inverse-render-proc f samples color width style alpha label) area)
|
|
(match-define (vector x-ivl y-ivl) (send area get-bounds-rect))
|
|
(match-define (sample ys xs x-min x-max) (f y-ivl samples))
|
|
|
|
(send area put-alpha alpha)
|
|
(send area put-pen color width style)
|
|
(send area put-lines (map vector xs ys))
|
|
|
|
(cond [label (line-legend-entry label color width style)]
|
|
[else empty]))
|
|
|
|
(defproc (inverse [f (real? . -> . real?)]
|
|
[y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
|
|
[#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
|
|
[#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
|
|
[#:color color plot-color/c (line-color)]
|
|
[#:width width (>=/c 0) (line-width)]
|
|
[#:style style plot-pen-style/c (line-style)]
|
|
[#:alpha alpha (real-in 0 1) (line-alpha)]
|
|
[#:label label (or/c string? #f) #f]
|
|
) renderer2d?
|
|
(define x-ivl (ivl x-min x-max))
|
|
(define y-ivl (ivl y-min y-max))
|
|
(define g (inverse->sampler f y-ivl))
|
|
(renderer2d (vector x-ivl y-ivl)
|
|
(inverse-bounds-fun g samples)
|
|
default-ticks-fun
|
|
(inverse-render-proc g samples color width style alpha label)))
|
|
|
|
;; ===================================================================================================
|
|
;; Kernel density estimation
|
|
|
|
(defproc (density [xs (sequence/c real?)] [bw-adjust real? 1]
|
|
[#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
|
|
[#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
|
|
[#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
|
|
[#:color color plot-color/c (line-color)]
|
|
[#:width width (>=/c 0) (line-width)]
|
|
[#:style style plot-pen-style/c (line-style)]
|
|
[#:alpha alpha (real-in 0 1) (line-alpha)]
|
|
[#:label label (or/c string? #f) #f]
|
|
) renderer2d?
|
|
(let ([xs (sequence->list xs)])
|
|
(define n (length xs))
|
|
(define sd (sqrt (- (/ (sum sqr xs) n) (sqr (/ (sum values xs) n)))))
|
|
(define h (* bw-adjust 1.06 sd (expt n -0.2)))
|
|
(define-values (f fx-min fx-max) (kde xs h))
|
|
(let ([x-min (if x-min x-min fx-min)]
|
|
[x-max (if x-max x-max fx-max)])
|
|
(function f x-min x-max #:y-min y-min #:y-max y-max #:samples samples
|
|
#:color color #:width width #:style style #:alpha alpha #:label label))))
|