On Wed, 2015-04-15 at 22:42 -0700, Brendan Tracey wrote:
> - When using plotinum, there were three main things that were
> frustrating (everything else was minor).
> 1) No colored scatter.
Have you filed an issue for this? If not, please do - I vaguely recall
discussion about this and I think there is was debate about its merits,
but an issue presumably would help it along.
> 2) Hard to scale the plot resolution
> 3) Using []struct{X,Y float64} instead of struct{X,Y []float64}.
Because e.g. XYer is an interface, you can use the second type if you
implement Len and XY on that type:
type structXY struct {
X, Y []float64
}
func (xy structXY) Len() int {
if len(xy.X) != len(xy.Y) {
panic("data slice length mismatch")
}
return len(xy.X)
}
func (xy structXY) XY(i int) (x, y float64) {
return xy.X[i], xy.Y[i]
}
> 1) is a feature request, so irrelevant here, and I believe 2 has
> already been fixed. I have mentioned 3 in the past, but I don't
> remember seeing any decisions on fixing on one or the other or both.
> It should be decided before the API is fixed. Personally, I much more
> often have data as slices (for example, a single set of x data with
> multiple y sets)
>
> - Coming up with a good design for Panels seems like a good idea.
Yes, this was the primary motivator for the OP.
> Another use is heat maps/colored scatter to show the legend of
> colors. We should at least think about it enough that we know we can
> implement it without backward incompatibilities. For example, maybe a
> Plot is a series of panels, one of which is the main plot area. This
> may require changing some of the canvas stuff
Chris Tessum expressed an interest in implementing a legend for HeatMap
(adding a Thumbnailer to HeatMap) - I think this is probably an easier
approach to this problem.
> - I don't like the design of Palettes. Fundamentally, it should be
> along the lines of
> type Palette interface {
> Color(float64) color.Color
> }
> i.e. a Palette is a function for associating a color to each value.
This is a fundamental issue with how palettes work. There has been some
discussion about formalising the notion of sequential and qualitative
palettes as interfaces in the palette package. I think this better
handles the variety of behaviours of the three different classes of
palettes; I would be very worried if a client could get a qualitative
palette and call Color(float64) on that.
I propose for palette:
// Sequential represents a sequentially ordered color palette.
type Sequential interface {
Palette
// Color returns a fractional color from the
// palette over the interval [0,1]. If f does
// not correspond to an element of the palette,
// it is calculated by interpolation.
Color(f float64) color.Color
}
// Qualitative represents a qualitative unordered color palette.
type Qualitative interface {
Palette
// Label returns the label of the ith color.
Label(i int) string
}
and the following addition to Diverging (renamed from DivergingPalette):
// Diverging is a collection of colors ordered into a palette
// with a critical class or break in the middle of the color range.
type Diverging interface {
Palette
// Color returns a fractional color from the
// palette over the interval [0,1]. If f does
// not correspond to an element of the palette,
// it is calculated by interpolation.
Color(f float64) color.Color
// CriticalIndex returns the indices of the lightest
// (median) color or colors in the Diverging, this
// corresponds to the colors at or adjacent to the
// color returned by Color(0.5).
// The low and high index values will be equal when
// there is a single median color.
CriticalIndex() (low, high int)
}
The reason these are not composable (Color() is not wrapped by its own
interface) is that I don't believe that it is reasonable to compose
these types of palettes in the real world.
> This could be a set of banded colors (like the available heat maps),
> could be a set of continuous colors, or could be something like "Use
> Rainbow except for NaN/inf which make black" or "make 1.267 green
> because it's special". These are easy to encode in a function, and
> hard to encode with just a list of colors. The plotter then just needs
> to query the pallette to find the appropriate color.
>
> - On the error issue, we might consider some form of non-error
> indication. For example, the fmt package is really nice in that
> something happens even if you have a mismatch in the number of
> elements and the number of format strings. Often with print
> statements, it's really nice that a basic error there doesn't crash my
> program, since it wasn't that important to begin with. I feel
> similarly to plotting. Most of the plots I make are not for
> publication. The point is to see how something looks, for example to
> verify that things are working correctly. In this case, I'd rather
> have the plot write something ugly that's along the lines of my
> request than to panic and crash the program. So, in WriterTo for
> example, maybe write the plot even if there are errors (probably with
> some sort of on-plot moniker that errors were present), and also
> return the error.
I quite like this idea - sort of like the diagonal banded DRAFT you see
on draft documents.