// Copyright ©2015 The Gonum Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Copyright ©2013 The bíogo Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Palette type comments ©2002 Cynthia Brewer. // Package brewer provides Brewer Palettes for informative graphics. // // The colors defined here are from http://www.ColorBrewer.org/ by Cynthia A. Brewer, // Geography, Pennsylvania State University. // // For more information see: // http://www.personal.psu.edu/cab38/ColorBrewer/ColorBrewer_learnMore.html package brewer // import "gonum.org/v1/plot/palette/brewer" import ( "errors" "fmt" "image/color" "gonum.org/v1/plot/palette" ) // Color represents a Brewer Palette color. type Color struct { Letter byte color.Color } // Usability describes the usability of a palette for particular use cases. type Usability byte const ( NotAvalailable Usability = iota Bad Unsure Good ) // Palette represents a color scheme. type Palette struct { ID string Name string Laptop Usability CRT Usability ColorBlind Usability Copy Usability Projector Usability Color []color.Color } // DivergingPalette represents a diverging color scheme. type DivergingPalette Palette // Colors returns the palette's color collection. func (d DivergingPalette) Colors() []color.Color { return d.Color } // CriticalIndex returns the indices of the lightest (median) color or colors in the DivergingPalette. // The low and high index values will be equal when there is a single median color. func (d DivergingPalette) CriticalIndex() (low, high int) { l := len(d.Color) return (l - 1) / 2, l / 2 } // NonDivergingPalette represents sequential or qualitative color schemes. type NonDivergingPalette Palette // Colors returns the palette's color collection. func (d NonDivergingPalette) Colors() []color.Color { return d.Color } // Diverging schemes put equal emphasis on mid-range critical values and extremes // at both ends of the data range. The critical class or break in the middle of the // legend is emphasized with light colors and low and high extremes are emphasized // with dark colors that have contrasting hues. type Diverging map[int]DivergingPalette // Qualitative schemes do not imply magnitude differences between legend classes, // and hues are used to create the primary visual differences between classes. // Qualitative schemes are best suited to representing nominal or categorical data. type Qualitative map[int]NonDivergingPalette // Sequential schemes are suited to ordered data that progress from low to high. // Lightness steps dominate the look of these schemes, with light colors for low // data values to dark colors for high data values. type Sequential map[int]NonDivergingPalette var ( // DivergingPalettes is a string-based map look-up table of diverging palettes. DivergingPalettes map[string]Diverging = diverging // QualitativePalettes is a string-based map look-up table of qualitative palettes. QualitativePalettes map[string]Qualitative = qualitative // SequentialPalettes is a string-based map look-up table of sequential palettes. SequentialPalettes map[string]Sequential = sequential ) // PaletteType indicates palette type for a GetPalette request. type PaletteType int const ( TypeAny PaletteType = iota TypeDiverging TypeQualitative TypeSequential ) // GetPalette returns a Palette based on palette type and name, and the number of colors // required. An error is returned if the palette name or type is not known or the requested // palette does not support the required number of colors. func GetPalette(typ PaletteType, name string, colors int) (palette.Palette, error) { if colors < 3 { return nil, errors.New("brewer: number of colors must be 3 or greater") } var ( p palette.Palette nameOk, colorsOk bool ) switch typ { case TypeAny: var pt interface{} pt, nameOk = all[name] if !nameOk { break } switch pt := pt.(type) { case Diverging: p, colorsOk = pt[colors] case Qualitative: p, colorsOk = pt[colors] case Sequential: p, colorsOk = pt[colors] default: panic("brewer: unexpected type") } case TypeDiverging: var pt Diverging pt, nameOk = diverging[name] if !nameOk { break } p, colorsOk = pt[colors] case TypeQualitative: var pt Qualitative pt, nameOk = qualitative[name] if !nameOk { break } p, colorsOk = pt[colors] case TypeSequential: var pt Sequential pt, nameOk = sequential[name] if !nameOk { break } p, colorsOk = pt[colors] default: return nil, fmt.Errorf("brewer: palette type not known: %v", typ) } if !nameOk { return nil, fmt.Errorf("brewer: palette %q not known", name) } if !colorsOk { return nil, fmt.Errorf("brewer: palette %q does not support %d colors", name, colors) } return p, nil }