Skip to content
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

Add color map support for selecting colors for renderers #52

Merged
merged 2 commits into from Apr 1, 2019

Conversation

alex-hhh
Copy link
Sponsor Collaborator

Plot renderers have a #:color argument which specifies the color to use for drawing, this can be a color% object, a RGB triplet, or an integer representing an index into a color palette. This commit introduces a mechanism to select which color palette (called a color map) to use when integers are used for the #:color argument of the renderers.

(require plot)
(parameterize ([plot-pen-color-map 'set1]
               [line-width 3])
    (plot (list (function sin -5 5 #:color 0)
                (function cos -5 5 #:color 1))))

sample-plot

The following new API functions are introduced and updated:

  • plot-pen-color-map and plot-brush-color-map are new parameters which specify the name of a color map to use for the #:color argument of renderer functions.

  • the ->pen-color and ->brush-color functions have been updated to use the current color map for lookups. These functions are used internally to convert integers to a RGB triplet, but they are also available in plot/utils.

  • The plot-foreground and plot-background parameters have been changed to "black" and "white" respectively, this was done to avoid drawing the axes and text in the first color of the pen color map and the background in the first color of the brush color map.

  • color-map-names is a new function which returns the list of color map names as a list of symbols.

  • color-map-size is a function which returns the number of colors in a color map. Note that ->pen-color and ->brush-color will cycle the colors in the color map, so any integer argument is valid for these functions.

  • register-color-map allows registering new color maps.

The last three functions are available in the plot/utils module, but not plot. This is consistent with the availability of ->pen-color.

The following color map names are also added, they are based on the matplotlib and ggplot2 color maps and use the same names: dark2, paired, pastel1, pastel2, set1, set2, set3, tab10, tab10n, tab20, tab20b and tab20c.

color-maps

The default plot colors are not changed with this commit, if the user does not specify a color map using plot-pen-color-map or plot-brush-color-map, the plot will use the same colors as before.

Some functions have been moved to different files, this was done to avoid circular dependencies.

Some other notes

  • There is a racket-lang discution about this feature here

  • This pull request does not cover using contour colors for various 3d plots or changing the defaults for the color maps, these can be addressed in subsequent pull requests

  • The color maps use list of three bytes as color definitions, this is consistent with what ->pen-color returns, and has not changed -- it is not very convenient for using this feature outside the plot package, but it is consistent with how the plot package works.

  • Once everyone is happy with the defined API, I will update the Scribble documentation and push the changes to this pull request.

The color map picture was generated using the code below, which also illustrates how to use color-map-names and color-map-size:

#lang racket
(require plot plot/utils pict racket/draw)

(define (pp-color-maps (width 400) (height 30))
  (define cm-names (sort (color-map-names)
                         (lambda (a b)
                           (string<=? (symbol->string a) (symbol->string b)))))
  (define cm-labels
    (for/list ([cm cm-names])
      (text (symbol->string cm) null 16)))
  (define cm-picts
    (for/list ([cm cm-names])
      (parameterize ([plot-pen-color-map cm])
        (define w (/ width (color-map-size cm)))
        (apply
         hc-append 0
         (for/list ([c (in-range (color-map-size cm))])
           (match-define (list r g b) (->pen-color c))
           (define color (make-object color% r g b))
           (filled-rectangle w height #:draw-border? #f #:color color))))))
  (define picts
    (let loop ([result '()]
               [labels cm-labels]
               [picts cm-picts])
      (if (null? labels)
          (reverse result)
          (loop (cons (car picts) (cons (car labels) result))
                (cdr labels)
                (cdr picts)))))
  (table 2 picts lc-superimpose cc-superimpose 15 3))

Plot renderers have a `#:color` argument which specifies the color to use for
drawing, this can be a `color%` object, a RGB triplet, or an integer
representing an index into a color palette.  This commit introduces a
mechanism to select which color palette (called a color map) to use when
integers are used for the `#:color` argument of the renderers.

```racket
(require plot)
(parameterize ([plot-pen-color-map 'set1]
               [line-width 3])
    (plot (list (function sin -5 5 #:color 0)
                (function cos -5 5 #:color 1))))
```

The following new API functions are introduced and updated:

* `plot-pen-color-map` and `plot-brush-color-map` are new parameters which
  specify the name of a color map to use for the `#:color` argument of
  renderer functions.

* the `->pen-color` and `->brush-color` functions have been updated to use the
  current color map for lookups. These functions are used internally to
  convert integers to a RGB triplet, but they are also available in
  `plot/utils`.

* The `plot-foreground` and `plot-background` parameters have been changed to
  "black" and "white" respectively, this was done to avoid drawing the axes
  and text in the first color of the pen color map and the background in the
  first color of the brush color map.

* `color-map-names` is a new function which returns the list of color map
  names as a list of symbols.

* `color-map-size` is a function which returns the number of colors in a color
  map.  Note that `->pen-color` and `->brush-color` will cycle the colors in
  the color map, so any integer argument is valid for these functions.

* `register-color-map` allows registering new color maps.

The last three functions are available in the `plot/utils` module, but not
`plot`.  This is consistent with the availability of `->pen-color`.

The following color map names are also added, they are based on the matplotlib
and ggplot2 color maps and use the same names: dark2, paired, pastel1,
pastel2, set1, set2, set3, tab10, tab10n, tab20, tab20b and tab20c.

The default plot colors are not changed with this commit, if the user does not
specify a color map using `plot-pen-color-map` or `plot-brush-color-map`, the
plot will use the same colors as before.

Some functions have been moved to different files, this was done to avoid
circular dependencies.
@alex-hhh
Copy link
Sponsor Collaborator Author

I have also updated the scribble documentation for the new functions. This pull request now has all the changes I proposed.

@alex-hhh
Copy link
Sponsor Collaborator Author

Hi @bennn , can you please review this pull request or ask someone else in the Racket team to review it? Thanks, Alex.

@bennn
Copy link
Contributor

bennn commented Mar 30, 2019

I can't review this until next weekend.

I think others are aware of this PR because of the mailing list discussion, but I'll advertise it on the Racket slack channel tomorrow & see if that catches anyone.

@jeapostrophe
Copy link

I've reviewed the code and will merge it.

@jeapostrophe jeapostrophe merged commit 0e30a09 into racket:master Apr 1, 2019

Register a new color map @racket[name] with the colors being a vector of RGB
triplets. If a color map by that name already exists, it is replaced.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add @history annotations on these new functions?

Copy link
Sponsor Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do that in a separate pull request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants