Skip to content

Jitter options & parameters (for plotting points) #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions plot-doc/plot/scribblings/params.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ The symbol, and its size and opacity, used in point plots.
Used as default keyword arguments of @racket[points] and @racket[points3d].
}

@deftogether[((defparam point-x-jitter x-jitter (>=/c 0) #:value 0)
(defparam point-y-jitter y-jitter (>=/c 0) #:value 0)
(defparam point-z-jitter z-jitter (>=/c 0) #:value 0))]{
When any of @(racket x-jitter), @(racket y-jitter), or @(racket z-jitter) are non-zero,
@(racket points) and @(racket points3d) will produce points randomly translated from their
original position along the x, y, or z axis, respectively.
For instance, if each parameter is set to 1, then @(racket points '(0 0)) will produce a random point
in a square of area 1 centered at @(racket '(0 0)).
Likewise @(racket points3d) will make a random point within a unit cube centered at @(racket '(0 0 0)).
}

@deftogether[((defparam point-color color plot-color/c #:value 0)
(defparam point-line-width width (>=/c 0) #:value 1))]{
The color and line width of symbols used in point plots and labeled points.
Expand Down
29 changes: 29 additions & 0 deletions plot-doc/plot/scribblings/renderer2d.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ Not every renderer-producing function has a @(racket #:label) argument; for exam
[#:sym sym point-sym/c (point-sym)]
[#:color color plot-color/c (point-color)]
[#:fill-color fill-color (or/c plot-color/c 'auto) 'auto]
[#:x-jitter x-jitter (>=/c 0) (point-x-jitter)]
[#:y-jitter y-jitter (>=/c 0) (point-y-jitter)]
[#:size size (>=/c 0) (point-size)]
[#:line-width line-width (>=/c 0) (point-line-width)]
[#:alpha alpha (real-in 0 1) (point-alpha)]
Expand All @@ -76,6 +78,33 @@ Readers of the first plot could only guess that the random points were generated

The @(racket #:sym) argument may be any integer, a Unicode character or string, or a symbol in @(racket known-point-symbols).
Use an integer when you need different points but don't care exactly what they are.

When @(racket x-jitter) or @(racket y-jitter) is non-zero, all points are randomly translated from their original position.
Specifically, each point @(racket p) is moved to a random location inside a rectangle centered at @(racket p) with width at most @(racket x-jitter) and height at most @(y-jitter).
The new points will lie within [@(racket x-min), @(racket x-max)] and [@(racket y-min), @(racket y-max)] if these bounds are non-@(racket #f).

@interaction[#:eval plot-eval
(plot
(points (for/list ([_i (in-range 999)])
(list (* 10 (random)) 0))
#:alpha 0.4
#:y-jitter 1
#:sym 'fullcircle1
#:color "blue")
#:x-min -5 #:x-max 5 #:y-min -5 #:y-max 5)]

Randomly moving data points is almost always a bad idea, but jittering in a controlled manner can sometimes be useful.
For example:
@margin-note{More examples of jittering:
@hyperlink["http://kieranhealy.org/blog/archives/2015/02/03/another-look-at-the-california-vaccination-data/"]{Another Look at the California Vaccination Data}
and
@hyperlink["https://pavelfatin.com/typing-with-pleasure/"]{Typing with Pleasure}}

@itemlist[
@item{To highlight the size of a dense (or @hyperlink["https://en.wiktionary.org/wiki/overplotting"]{overplotted}) sample.}
@item{To see the distribution of 1-dimensional data; as a substitute for box or violin plots.}
@item{To anonymize spatial data, showing i.e. an office's neighborhood but hiding its address.}
]
}

@defproc[(vector-field
Expand Down
10 changes: 10 additions & 0 deletions plot-doc/plot/scribblings/renderer3d.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ See @secref["renderer2d-function-arguments"] for a detailed example.
[#:sym sym point-sym/c (point-sym)]
[#:color color plot-color/c (point-color)]
[#:fill-color fill-color (or/c plot-color/c 'auto) 'auto]
[#:x-jitter x-jitter (>=/c 0) (point-x-jitter)]
[#:y-jitter y-jitter (>=/c 0) (point-y-jitter)]
[#:z-jitter z-jitter (>=/c 0) (point-z-jitter)]
[#:size size (>=/c 0) (point-size)]
[#:line-width line-width (>=/c 0) (point-line-width)]
[#:alpha alpha (real-in 0 1) (point-alpha)]
Expand All @@ -51,6 +54,13 @@ For example, a scatter plot of points sampled uniformly from the surface of a sp

(plot3d (points3d (map vector xs ys zs) #:sym 'dot)
#:altitude 25)]

When @(racket x-jitter), @(racket y-jitter), or @(racket z-jitter) is non-zero,
each point @(racket p) is translated to a random location inside a box centered at @(racket p) with width @(racket x-jitter), height @(racket y-jitter), and depth @(racket z-jitter).
The new points will lie within [@(racket x-min), @(racket x-max)] etc. if these bounds are non-@(racket #f).

Note that adding random noise to data, via jittering or otherwise, is usually a bad idea.
See the documentation for @(racket points) for examples where jittering may be appropriate.
}

@defproc[(vector-field3d
Expand Down
21 changes: 21 additions & 0 deletions plot-lib/plot/private/common/math.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,27 @@
[x (if a (max x a) x)])
x))

;; Return a Real drawn randomly from the interval [(- val jitter) (+ val jitter)].
;; If #:ivl is given, result will lie within the given interval.
(: apply-jitter (->* [Real Nonnegative-Real] [#:ivl ivl] Real))
(define (apply-jitter val jitter #:ivl [interval unknown-ivl])
(let ([offset (* (random) jitter)])
(if (zero? (random 2))
(let ([val- (- val offset)])
(max val- (or (ivl-min interval) val-)))
(let ([val+ (+ val offset)])
(min val+ (or (ivl-max interval) val+))))))

;; Precondition: all vectors in the arguments are the same length
(:: points-apply-jitters (->* [(Listof (Vectorof Real)) (Vectorof Nonnegative-Real)] [#:ivls (U (Vectorof ivl) #f)] Void))
(define (points-apply-jitters vals jitters #:ivls [ivls #f])
(for ([v (in-list vals)])
(for ([i (in-range (vector-length jitters))])
(let ([v_i (vector-ref v i)]
[iv (if ivls (vector-ref ivls i) unknown-ivl)]
[jt (vector-ref jitters i)])
(vector-set! v i (apply-jitter v_i jt #:ivl iv))))))

;; ===================================================================================================
;; Rectangles

Expand Down
3 changes: 3 additions & 0 deletions plot-lib/plot/private/common/parameters.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@

(defparam point-sym Point-Sym 'circle)
(defparam point-color Plot-Color 0)
(defparam point-x-jitter Real 0)
(defparam point-y-jitter Real 0)
(defparam point-z-jitter Real 0)
(defparam2 point-size Real Nonnegative-Real 6 (nonnegative-rational 'point-size))
(defparam2 point-line-width Real Nonnegative-Real 1 (nonnegative-rational 'point-line-width))
(defparam2 point-alpha Real Nonnegative-Real 1 (unit-ivl 'point-alpha))
Expand Down
27 changes: 17 additions & 10 deletions plot-lib/plot/private/plot2d/point.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#:sym Point-Sym
#:color Plot-Color
#:fill-color (U Plot-Color 'auto)
#:x-jitter Nonnegative-Real
#:y-jitter Nonnegative-Real
#:size Nonnegative-Real
#:line-width Nonnegative-Real
#:alpha Nonnegative-Real
Expand All @@ -50,6 +52,8 @@
#:sym [sym (point-sym)]
#:color [color (point-color)]
#:fill-color [fill-color 'auto]
#:x-jitter [x-jitter (point-x-jitter)]
#:y-jitter [y-jitter (point-y-jitter)]
#:size [size (point-size)]
#:line-width [line-width (point-line-width)]
#:alpha [alpha (point-alpha)]
Expand All @@ -67,16 +71,19 @@
[vs (filter vrational? vs)])
(cond
[(empty? vs) (renderer2d #f #f #f #f)]
[else (match-define (list (vector #{xs : (Listof Real)} #{ys : (Listof Real)}) ...) vs)
(let ([x-min (if x-min x-min (apply min* xs))]
[x-max (if x-max x-max (apply max* xs))]
[y-min (if y-min y-min (apply min* ys))]
[y-max (if y-max y-max (apply max* ys))]
[fill-color (if (eq? fill-color 'auto) (->pen-color color) fill-color)])
(renderer2d
(vector (ivl x-min x-max) (ivl y-min y-max)) #f default-ticks-fun
(points-render-fun vs sym color fill-color
size line-width alpha label)))]))]))
[else
(unless (= 0 x-jitter y-jitter)
(points-apply-jitters vs (vector x-jitter y-jitter) #:ivls (vector (ivl x-min x-max) (ivl y-min y-max))))
(match-define (list (vector #{xs : (Listof Real)} #{ys : (Listof Real)}) ...) vs)
(let ([x-min (if x-min x-min (apply min* xs))]
[x-max (if x-max x-max (apply max* xs))]
[y-min (if y-min y-min (apply min* ys))]
[y-max (if y-max y-max (apply max* ys))]
[fill-color (if (eq? fill-color 'auto) (->pen-color color) fill-color)])
(renderer2d
(vector (ivl x-min x-max) (ivl y-min y-max)) #f default-ticks-fun
(points-render-fun vs sym color fill-color
size line-width alpha label)))]))]))

;; ===================================================================================================
;; Vector fields
Expand Down
11 changes: 11 additions & 0 deletions plot-lib/plot/private/plot3d/point.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
#:sym Point-Sym
#:color Plot-Color
#:fill-color (U Plot-Color 'auto)
#:x-jitter Nonnegative-Real
#:y-jitter Nonnegative-Real
#:z-jitter Nonnegative-Real
#:size Nonnegative-Real
#:line-width Nonnegative-Real
#:alpha Nonnegative-Real
Expand All @@ -51,6 +54,9 @@
#:sym [sym (point-sym)]
#:color [color (point-color)]
#:fill-color [fill-color 'auto]
#:x-jitter [x-jitter (point-x-jitter)]
#:y-jitter [y-jitter (point-y-jitter)]
#:z-jitter [z-jitter (point-z-jitter)]
#:size [size (point-size)]
#:line-width [line-width (point-line-width)]
#:alpha [alpha (point-alpha)]
Expand All @@ -70,6 +76,11 @@
[vs (filter vrational? vs)])
(cond [(empty? vs) (renderer3d #f #f #f #f)]
[else
(unless (= 0 x-jitter y-jitter z-jitter)
(points-apply-jitters vs (vector x-jitter y-jitter z-jitter)
#:ivls (vector (ivl x-min x-max)
(ivl y-min y-max)
(ivl z-min z-max))))
(match-define (list (vector #{xs : (Listof Real)}
#{ys : (Listof Real)}
#{zs : (Listof Real)})
Expand Down
3 changes: 3 additions & 0 deletions plot-lib/plot/private/utils-and-no-gui.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@
point-sym
point-color
point-size
point-x-jitter
point-y-jitter
point-z-jitter
point-line-width
point-alpha
vector-field-samples
Expand Down
1 change: 1 addition & 0 deletions plot-lib/plot/utils.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
ivl-translate
bounds->intervals
clamp-real
points-apply-jitters
;; Rectangles
Rect
rect-meet
Expand Down