facet

package module
v0.0.0-...-42b5f6e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 22, 2020 License: BSD-3-Clause Imports: 16 Imported by: 0

README

Faceted Plots

Faceted Plots provides faceted plot in the style of ggplot2. It builds on the work of gonum.org/v1/plot, especially the grafic.

Documentation

Overview

Package facet is an experimental package to produce faceted plots.

It tries to use or enhance gonum.org/v1/plot.

Scales

The concept of a scale is taken from ggplot2. Package facet knows about the following scales:

  • X-Scale The x- and y scale are mandatory for all faceted
  • Y-Scale plots. The scales are drawn as axis, not as guides.
  • Alpha-Scale The alpha (opacity) value
  • Color-Scale The line and symbol color
  • Fill-Scale The fill color
  • Shape-Scale The symbol used to draw points
  • Size-Scale The size of points and width of lines
  • Stroke-Scale The line style (dash pattern)

The Shape and Stroke scales cannot be continouos but must be discrete because only a discrete set of symbol types and line styles are available. The other scales can be discrete or continouos.

If a scale is used in a faceted plot a scale Guide is drawn to show how the scales range maps to aesthetics. Guides for different scales are combined iff:

  1. The two scales are of the same kind (discrete, continuous, ...)
  2. The two scales have the same range.
  3. The two scales have the same Title or the Title is empty.
  4. The scales must use the same Ticker.
  5. Fill and Color can be combined if they use the same ColorMap or one is empty.

Faceted Plots and Grouping

There are one dimensional groupings and two-dimensional groupings corresponding to facet_row, facet_column and facet_grid. Grouping is done on discrete values (which may be an intervall).

Scales

Scales have a wide varity of ranges.

  • Data: The range covered by actual data points This is learend by scanning during Range()
  • Interval (Limits): Data in this range is processed This range is determined by autoscaling from the learend data range or set manually.
  • Range: The range of the guides (axis and legends) This normaly is the same as the Interval/Limits. It is the range actually drawn which might clip processed data points or add margin.
  • Output: This are the pixel ranges on screen for position scales and the Size scale,

Ticks are generated for the Interval (but ticks outside of Range are not drawn).

The distinction of Interval/Limits and range for a position scale works like this.

Data == [10, 30]
  |
  | Autoscaling, relative expansion 5% = 1
  V
Interval == [9, 31]  --> Ticks generated: 10, 20, 30
  |
  | Range changed manualy to
  V
Range == [15, 45]
  The plot area is clipped below 15.
  Ticks stay the same, only 20 and 30 are drawn.

Being able to limit the Range is useful to "zoom in" into a plot. Expanding the range beyond the Limit is useful for the Size scale: If your Limits are [20, 40] and you map that directly to point radius from [2px, 20px] a point representing a data value of 20 will be 10 times smaller in radius and 100 times smaller in area than a data point with value 40. Here you might set the range to [0, 40] but still draw breaks/ticks and thus legend entries only for 20, 25, 30, 35 and 40.

A Transformation is responsible for two things:

  • Generate breaks for the given Interval/Limit
  • Take values from Interval/Limits (or Range of different) and map them to output coordinates

Output coordinates differ for different scales:

  • Position Scales: screen coordinates (x,y)
  • Color Scales: [0, 1] used to index a ColorMap
  • Size Scale: pixel size for radius or linewidth
  • Shape and Stroke Scale: ???

Scale Transformations

Scale transformations should work like the ones in ggplot2.

Index

Constants

View Source
const (
	XScale int = iota
	YScale
	AlphaScale
	ColorScale
	FillScale
	ShapeScale
	SizeScale
	StrokeScale
)

Variables

View Source
var DefaultColorMap = &Rainbow{
	Value:      0.9,
	Saturation: 0.9,
	HueGap:     1.0 / 6.0,
	min:        0,
	max:        1,
	alpha:      1,
}
View Source
var IdentityTrans = Transformation{
	Name:    "Identity",
	Trans:   func(from, to Interval, x float64) float64 { return x },
	Inverse: func(from, to Interval, y float64) float64 { return y },
	Ticker:  DefaultTicks(4),
}

IdentityTrans does not transform at all.

View Source
var InfinitInterval = Interval{math.Inf(-1), math.Inf(+1)}

InfinitInterval is the interval [-Inf, +Inf] endpoints.

View Source
var LinearTrans = Transformation{
	Name: "Linear",
	Trans: func(from, to Interval, x float64) float64 {
		return to.Min + (to.Max-to.Min)*(x-from.Min)/(from.Max-from.Min)
	},
	Inverse: func(from, to Interval, y float64) float64 {
		return to.Min + (to.Max-to.Min)*(y-from.Min)/(from.Max-from.Min)
	},
	Ticker: DefaultTicks(4),
}

LinearTrans implements a linear mapping of from to to.

View Source
var Log10Trans = Transformation{
	Name: "Log10",
	Trans: func(from, to Interval, x float64) float64 {
		t := math.Log10(x/from.Min) / math.Log10(from.Max/from.Min)
		y := to.Min + t*(to.Max-to.Min)
		return y
	},
	Inverse: func(from, to Interval, y float64) float64 {
		return to.Min * math.Pow(10, math.Log10(to.Max/to.Min)*(y-from.Min)/(from.Max-from.Min))
	},
	Ticker: plot.LogTicks{},
}
View Source
var SqrtTrans = Transformation{
	Name: "SquareRoot",
	Trans: func(from, to Interval, x float64) float64 {
		area := Interval{to.Min * to.Min, to.Max * to.Max}
		return math.Sqrt(LinearTrans.Trans(from, area, x))
	},
	Inverse: func(from, to Interval, y float64) float64 {
		area := Interval{from.Min * from.Min, from.Max * from.Max}
		return LinearTrans.Trans(area, to, y*y)
	},
	Ticker: DefaultTicks(5),
}

SqrtTrans implements a square root transformation suitable to map the Size aesthetic to the size of a point. (Ggplots scale_size)

View Source
var SqrtTransFix0 = Transformation{
	Name: "SquareRoot",
	Trans: func(from, to Interval, x float64) float64 {
		from.Min, to.Min = 0, 0
		area := Interval{to.Min * to.Min, to.Max * to.Max}
		return math.Sqrt(LinearTrans.Trans(from, area, x))
	},
	Inverse: func(from, to Interval, y float64) float64 {
		from.Min, to.Min = 0, 0
		area := Interval{from.Min * from.Min, from.Max * from.Max}
		return LinearTrans.Trans(area, to, y*y)
	},
	Ticker: DefaultTicks(5),
}

SqrtTransFix0 implements a square root transformation suitable to map the Size aesthetic to the area of a point. It maps 0 to 0. (Ggplot's scale_size_are)

View Source
var UnsetInterval = Interval{math.NaN(), math.NaN()}

UnsetInterval is the interval with unsepcified (NaN) endpoints.

Functions

This section is empty.

Types

type Aesthetic

type Aesthetic func(i int) float64

Aestetic is a function mapping a certain data point to an aestehtic.

type Autoscaling

type Autoscaling struct {
	// Expand determines how much the actual data range is expandend.
	Expand struct {
		Absolute  float64
		Releative float64
	}

	MinRange Interval // MinRange determines the allowed range of the Min of a scale.
	MaxRange Interval // MaxRange determines the allowed range of the Max of a scale.
}

Autoscaling controls how the min and max value of a scale are scaled. Setting a range to a degenerate interval [f:f] will turn of autoscaling and fix the value to f. A non-degenerate range [u:v] will allow autoscaling between u and v. A NaN value works like -Inf for u and +Inf for v.

type DataRanges

type DataRanges [numScales]Interval

DataRanges contains all the ranges covered by some data.

func NewDataRanges

func NewDataRanges() DataRanges

NewDataRange returns a DataRange with all intervals unset, i.e. [NaN,NaN].

type DefaultTicks

type DefaultTicks int

DefaultTicks is suitable for the Tick.Marker field of an Axis, it returns a reasonable default set of tick marks.

func (DefaultTicks) Ticks

func (dt DefaultTicks) Ticks(min, max float64) []plot.Tick

Ticks returns Ticks in the specified range.

type DiscreteAesthetic

type DiscreteAesthetic func(i int) int

DiscreteAestetic is a function mapping a certain data point to a discrete aesthetic like Shape or Stroke.

type DiscreteTicks

type DiscreteTicks struct{}

func (DiscreteTicks) Ticks

func (DiscreteTicks) Ticks(min, max float64) []plot.Tick

Ticks makes DiscreteTicks implements plot.Ticker.

type FGeom

type FGeom interface {
	// N returns the number of geoms in this data set.
	N() int

	// Group of the i'th geom in this data set.
	Group(i int) GroupID

	// DataRange returns what ranges on which scales are covered by
	// covered by the geoms indexed by subset
	DataRange(subset []int) DataRanges

	// Draw is called to draw the geoms indexed by subset onto p.
	Draw(p *Panel, subset []int)
}

A FGeom is the geometrical representation of some faceted data.

type FacetPlot

type FacetPlot struct {
	// Title is the optional plot title.
	Title string

	Geoms []FGeom

	// Rows and Cols are number of rows and columns in the faceted plot.
	Rows, Cols int
}

FacetPlot describes a automatically facetted plot.

type Faceting

type Faceting struct {
	Rows   []string
	Cols   []string
	Groups map[GroupID][]int // Groups contains the indices for each group
}

Faceting

func NewFaceting

func NewFaceting() *Faceting

func (*Faceting) Add

func (f1 *Faceting) Add(group GroupID)

type Geom

type Geom interface {
	// DataRange returns what ranges on which scales are covered by
	// covered by the geoms indexed by subset
	DataRange() DataRanges

	// Draw is called to draw the geoms indexed by subset onto p.
	Draw(p *Panel)
}

A Geom is the geometrical representation of some data.

type GroupBy

type GroupBy struct {
	FacetRow DiscreteAesthetic
	FacetCol DiscreteAesthetic
	Alpha    Aesthetic
	Color    Aesthetic
	Fill     Aesthetic
	Shape    DiscreteAesthetic
	Size     Aesthetic
	Stroke   DiscreteAesthetic
}

type GroupID

type GroupID struct {
	Row, Col string
}

A GroupID identifies a set of values belonging together.

type Grouper

type Grouper interface {
	Group() GroupID
}

type Interval

type Interval struct {
	Min, Max float64
}

Interval represents a (potentially degenerate) real interval. Both edges of the interval may be NaN indicating this edge is not set determined.

func (*Interval) Degenerate

func (i *Interval) Degenerate() (modified bool)

Degenerate the intervall i by replacing NaN and Inf with -1 (for Min) and +1 (for Max) and by exapnding collapsed intervals of the form [a, a].

func (Interval) Equal

func (i Interval) Equal(j Interval) bool

func (*Interval) Update

func (i *Interval) Update(x ...float64)

Update expands i to include x.

type Layer

type Layer struct {
}

type Panel

type Panel struct {
	Title  string
	Plot   *Plot
	Geoms  []Geom
	Canvas draw.Canvas
	Scales [numScales]*Scale
}

A Panel represents one panel in a faceted plot.

func (*Panel) InRangeXY

func (p *Panel) InRangeXY(x, y float64) bool

func (*Panel) MapColor

func (p *Panel) MapColor(v float64) color.Color

MapColor maps a data value v to a color by calling p.Plot.MapColor(v,false).

func (*Panel) MapFill

func (p *Panel) MapFill(v float64) color.Color

MapFill maps a data value v to a color by calling p.Plot.MapColor(v,true).

func (*Panel) MapSize

func (p *Panel) MapSize(v float64) vg.Length

MapSize maps a data value v to a display size by calling p.Plot.MapSize.

func (*Panel) MapXY

func (p *Panel) MapXY(x, y float64) vg.Point

MapXY maps the data coordinate (x,y) to a canvas point.

type Partitioner

type Partitioner struct {
	Partitions int
	Range      Interval
}

A Partitioner can be used to turn a continuous value into a discrete factor.

func (*Partitioner) Learn

func (p *Partitioner) Learn(x ...float64)

func (*Partitioner) Partition

func (p *Partitioner) Partition(x float64) string

type Plot

type Plot struct {
	// Title is the optional plot title.
	Title string

	// Rows and Cols are number of rows and columns in the faceted plot.
	Rows, Cols int

	// Panels is the matirx of plot panels: Panels[r][c] is the
	// panel at row r and column c.
	Panels [][]*Panel

	// RowLabels and ColLabels contain the optional strip titles
	// for the row and column strips of a grid layout.
	RowLabels, ColLabels []string

	// XScales are the scales for the Col many x-axes. If the x scales
	// are not free all x-axes will share the same scale.
	XScales []*Scale

	// YScales are the scales for the Row many y-axes. If the y scales
	// are not free all y-axes will share the same scale.
	YScales []*Scale

	// Scales contains the rest of the scales like Color, Fill, Shape, etc.
	Scales [numScales]*Scale // Except X and Y

	// ColorMap and FillMap are used to map the ColorScale and FillScale
	// to a color
	ColorMap, FillMap palette.ColorMap

	// Style used during plotting. TODO: Keep here?
	Style Style

	// Messages is used to report warnings and errors during creation
	// of the plot.
	Messages io.Writer
}

Plot describes a facetted plot.

func GeneratePlot

func GeneratePlot(fp FacetPlot) *Plot

func NewPlot

func NewPlot(rows, cols int, freeX, freeY bool) *Plot

NewPlot creates a new faceted plot in a grid layout with row * col many panels. All columns share the same X-scale and all rows share the same Y-scale unless freeX or respectively freeY is specified.

func NewSimplePlot

func NewSimplePlot() *Plot

NewSimple creates a new un-faceted plot, that is a plot with just one panel.

func (*Plot) Autoscale

func (p *Plot) Autoscale()

Autoscale all scales based on the current Data range.

func (*Plot) DeDegenerateXandY

func (p *Plot) DeDegenerateXandY()

DeDegenerateXandY makes sure the Limit intervall for all X and Y scales in p are not degenerated: NaN and Inf are turned into -1 (Min) or +1 (Max) degenerate intervalls of the form [a, a] are exapnded around a.

func (*Plot) Draw

func (f *Plot) Draw(c draw.Canvas) error

Draw renders f to c.

func (*Plot) LearnDataRange

func (p *Plot) LearnDataRange()

LearnDataRange determines the the range the data covers in all scales.

func (*Plot) MapColor

func (p *Plot) MapColor(v float64, fill bool) color.Color

MapColor maps the data value v to a color via p's ColorMap or FillMap if fill is true. Values outside if the relevant scale's intervall are mapped to Gray50 (which is what ggplot2 does).

func (*Plot) MapSize

func (p *Plot) MapSize(v float64) vg.Length

MapSize maps the data value s to a display length via f's size scale. Values outside of of the range of the size scale are mapped to 0.

func (*Plot) Prepare

func (p *Plot) Prepare()

Prepare learns the Data range of each scale, autoscales each scale's limit, clears each scales's range and degenrated the X and Y scales.

func (*Plot) SizeMap

func (f *Plot) SizeMap() func(x float64) vg.Length

func (*Plot) Warnf

func (p *Plot) Warnf(f string, args ...interface{})

type Rainbow

type Rainbow struct {
	Value      float64 // Value of the generated colors
	Saturation float64 // Saturation of the generated colors.
	StartHue   float64 // StartHue is the hue used for the Min value.
	HueGap     float64 // HueGap determines the fraction of the hue space which is not used.
	Number     int     // Number of colors generated by the Colors method.
	// contains filtered or unexported fields
}

Rainbow is a equaly spaced hue rainbow color map.

func (*Rainbow) Alpha

func (r *Rainbow) Alpha() float64

Alpha returns the opacity value of the ColorMap.

func (*Rainbow) At

func (r *Rainbow) At(x float64) (color.Color, error)

At returns the color mapped for x.

func (*Rainbow) Colors

func (r *Rainbow) Colors() []color.Color

Colors implements palette.Palette.Colors.

func (*Rainbow) Max

func (r *Rainbow) Max() float64

Max returns the current maximum value of the ColorMap.

func (*Rainbow) Min

func (r *Rainbow) Min() float64

Min returns the current minimum value of the ColorMap.

func (*Rainbow) Palette

func (r *Rainbow) Palette(colors int) palette.Palette

Palette records the number of colors and retunrs itself as a palettte.Palette so that subsequent calls to Color yield a palette with colors many colors.

func (*Rainbow) SetAlpha

func (r *Rainbow) SetAlpha(alpha float64)

SetAlpha sets the opacity value of the ColorMap. Zero is transparent and one is completely opaque. The default value of alpha should be expected to be one. The function should be expected to panic if alpha is not between zero and one.

func (*Rainbow) SetMax

func (r *Rainbow) SetMax(max float64)

SetMax sets the maximum value of the ColorMap.

func (*Rainbow) SetMin

func (r *Rainbow) SetMin(min float64)

SetMin sets the minimum value of the ColorMap.

type Scale

type Scale struct {
	// Title is the scale's title.
	Title string

	// Data is the range covered by actual data (in data units). It can be
	// populated from the actual data via LearnDataRange.
	Data Interval

	// Limit captures the range (in data units) of this scale. It may be
	// larger or smaller than the actual Data range.
	Limit Interval

	// Range is the output range of this scale and will be in different
	// units depending on the scale type:
	//   - Screen coordinates for X and Y scales
	//   - Screen length for Size scale
	//   - Opacity (between 0 and 1) for the Alpha scale.
	//   - Color (between 0 and 1) for Color and Fill scale
	//   - Integer between 0 and N for discrete scales
	Range Interval

	// Trans implements the mapping from Interval (Limits) to Range for
	// this scale.
	Trans Transformation

	// ScaleType determines the fundamental nature of the scale.
	ScaleType ScaleType

	// Autoscaling can be used to control autoscaling of this scale.
	Autoscaling

	// Ticker is responsible for generating the ticks.
	Ticker plot.Ticker

	// Values contains the nominal values. TODO: replace by Ticker
	Values []string

	// TimeFmt is used to format date/time tics.
	TimeFmt string
	// T0 is the reference time and timezone
	T0 time.Time
}

Scale is a generalizes axis: While a plot has exactly two axes (the x-axis and the y-axis) it can have more scales, e.g. a color scale, a linetype scale, a symbol scale or even a size scale.

func NewScale

func NewScale() *Scale

NewScale returns a new scale with all intervalls unset, an identitiy transformation and full, unexpanded autoscaling

func (*Scale) Autoscale

func (s *Scale) Autoscale()

Autoscale turns the Data range into an actual scale range.

func (*Scale) FixMax

func (s *Scale) FixMax(x float64)

FixMax fixes the max of s to x. . If x is NaN the max is determined by autoscaling to the actual data.

func (*Scale) FixMin

func (s *Scale) FixMin(x float64)

FixMin fixes the min of s to x. If x is NaN the min is determined by autoscaling to the actual data.

func (*Scale) HasData

func (s *Scale) HasData() bool

HasData reports whether the Data intervall of s is valid.

func (*Scale) InLimit

func (s *Scale) InLimit(x float64) bool

InLimit reports whether x lies in the Limit of s.

func (*Scale) InRange

func (s *Scale) InRange(x float64) bool

InRange reports whether x lies in the Range of s.

func (*Scale) Map

func (s *Scale) Map(x float64) float64

Map maps s's Range interval to [0, 1]. Values outside of [s.Range.Min, s.Range.Max] are mapped to values < 0 or > 1. If s's Intervall is degenerate or unset Map returns NaN.

func (*Scale) String

func (s *Scale) String() string

String returns a string suitable for debugging s.

func (*Scale) UpdateData

func (s *Scale) UpdateData(i Interval)

UpdateData updates s to cover i.

type ScaleType

type ScaleType int

ScaleType selects one of the handful know scale types.

const (
	Linear ScaleType = iota
	Discrete
	Time
	Logarithmic
)

func (ScaleType) String

func (st ScaleType) String() string

String returns the type of st.

type Style

type Style struct {
	Background color.Color

	Title       draw.TextStyle
	SubTitle    draw.TextStyle
	TitleHeight vg.Length

	Panel struct {
		Background color.Color
		PadX       vg.Length
		PadY       vg.Length
	}
	HStrip struct {
		Background color.Color
		Height     vg.Length
		draw.TextStyle
	}
	VStrip struct {
		Background color.Color
		Width      vg.Length
		draw.TextStyle
	}

	Grid struct {
		Major draw.LineStyle
		Minor draw.LineStyle
	}

	XAxis struct {
		Title       draw.TextStyle
		TitleHeight vg.Length
		Line        draw.LineStyle
		Expand      struct {
			Absolute  float64
			Releative float64
		}
		MajorTick struct {
			Number int
			draw.LineStyle
			Length vg.Length
			Align  draw.YAlignment
			Label  draw.TextStyle
		}
		MinorTick struct {
			draw.LineStyle
			Length vg.Length
			Align  draw.YAlignment
		}
	}

	YAxis struct {
		Title      draw.TextStyle
		TitleWidth vg.Length
		Line       draw.LineStyle
		Expand     struct {
			Absolute  float64
			Releative float64
		}
		MajorTick struct {
			Number int
			draw.LineStyle
			Length vg.Length
			Align  draw.XAlignment
			Label  draw.TextStyle
		}
		MinorTick struct {
			draw.LineStyle
			Length vg.Length
			Align  draw.XAlignment
		}
	}

	Legend struct {
		Position string // left
		Title    draw.TextStyle
		Label    draw.TextStyle

		Discrete struct {
			Size vg.Length
			Pad  vg.Length
		}
		Continuous struct {
			Size   vg.Length
			Length vg.Length
			Tick   struct {
				draw.LineStyle
				Length vg.Length
				Align  draw.XAlignment
				Mirror bool
			}
		}
	}

	GeomDefault struct {
		Color     color.Color
		FillColor color.Color
		LineWidth vg.Length
		Size      vg.Length
	}
}

A Style controls how a Plot is drawn.

func DefaultFacetStyle

func DefaultFacetStyle(baseFontSize vg.Length) Style

DefaultFacetStyle returns a FacetStyle which mimics the appearance of ggplot2. The baseFontSize is the font size for axis titles and strip labels, the title is a bit bigger, tick labels a bit smaller.

type Transformation

type Transformation struct {
	Name    string
	Trans   func(from, to Interval, x float64) float64
	Inverse func(from, to Interval, y float64) float64
	Ticker  plot.Ticker
}

A Transformation bundles two functions Trans and Inverse together with an appropiate Ticker. The two functions map two intervals.

Directories

Path Synopsis
Packag data contains various data interfaces and prototypical implementations.
Packag data contains various data interfaces and prototypical implementations.
Package geom provides basic geometric objects to display data in a plot.
Package geom provides basic geometric objects to display data in a plot.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL