hep icon indicating copy to clipboard operation
hep copied to clipboard

idea: hplot band-gradients

Open rigelrozanski opened this issue 4 years ago • 4 comments

It would be incredible to be able to not only display a color between two bands, but also display a gradient between two bands, potentially with checkpoint colours along the way.

// Gradient implements the plot.Plotter interface, drawing a colored band made of
// two lines.
type Gradient struct {
        bands []plotter.XYs // array of all gradient bands from top to bottom

	// outerLS is the style of the line contouring the gradient.
	// Use zero width to disable.
	outerLS draw.LineStyle

	// innerLS is the style of the lines within the gradient.
	// Use zero width to disable.
        innerLS draw.LineStyle

	// GradientTopColors/GradientBottomColors define 
        // the start/end colors for each of the gradient bands. 
	// Use nil to disable the filling. 
	GradientTopColors []color.Color 
	GradientBottomColors []color.Color 
}

This would be really cool to use in conjunction with percentile data, imagine the scatter plot here https://github.com/go-hep/hep/blob/master/hplot/testdata/s2d_band_golden.png except with a gradient line for the 10th, 25th, 50th, 75th, and 90th percentiles. It could lead to conveying a new level of richness of information of a dataset.

This idea is already somewhat possible with just using multiple bands, but one would need many many solid bands to get the real feel of a gradient and would be kind of cumbersome to implement on the user side. This being said, maybe the most straightforward way to implement this gradient feature within hplot is to simply linearly approximate a large number of tiny bands and associated colors between the provided Gradient.bands and plot them as bands with no conour borders, I'm sure with enough bands it would create that gradient feel. (or maybe there is an easier way, again just an idea)

Just an idea! Would be open to contributing to its development if there is interest here!

rigelrozanski avatar May 07 '20 18:05 rigelrozanski

thanks for your interest in hplot.

I must admit I am not completely sold on the idea of a gradient for the band use case (as I don't really see the physics analysis use case - but, admittedly, I haven't done any serious physics analysis in a very long time). that said, I do see the application for contour plots or - well - plotting physics gradients (e.g. an electromagnetic field gradient).

looking around a bit, I've noticed these 2 implementations of a gradient:

  • https://github.com/lucasb-eyer/go-colorful/blob/master/doc/gradientgen/gradientgen.go
  • https://godoc.org/golang.org/x/exp/shiny/iconvg/internal/gradient

both revolve around implementing a gradient as a type that implements image.Image. luckily, gonum/plot already provides the ability to draw an image.Image in a canvas.

so I guess it boils down to the minute details on how to describe/model a gradient and the mechanics on how to translate that into an image.Image.

what do you think? (perhaps this could be done at the gonum/plot level...)

sbinet avatar May 08 '20 07:05 sbinet

Hello! Okay, yeah so after digging a bit deeper and understanding what's actually happening here, I think the cleanest approach is implement something like a UpDownGradient (based off of the polygon type from https://github.com/gonum/plot/blob/master/plotter/polygon.go) Which would draw uniformly between the upper and lower colors along the "y" direction. Further creating the GradientBand similarly to the hplot/Band type would be a piece of cake.

type UpDownGradient struct {
	// Points representing the upper and lower 
        // bounding lines of the gradient, they must
        // have the same range. 
        UpperPts []vg.Point
        LowerPts []vg.Point

	// LineStyle is the style of the line around the edge
	// of the gradient.
	draw.LineStyle

	// Upper and Lower colors of the gradient
	ColorUpper color.Color
  	ColorLower color.Color
}

Now, I of course want access to something like the UpDownGradient for my own work, however I'm sure this type could be easily adapted to a GradientContour if an additional vector input such as GradientDirection was included. I think for visualization representing fields as gradients could certainly be useful. I actually had no idea that HEP was for high-energy-physics hehe - my bad! I'm actually really struggling right now to come up with a way to more accurately visualize a 4D manifold (aka Einstein's-spacetime) without assuming space as 2D (as all the general relativity depictions often show it as, so then the 3rd dimension is bend time)... It looks like these folks are using gradients in some novel visualization of 4D https://vcg.iwr.uni-heidelberg.de/static/publications/Hofmann2018topo4D.pdf. I digress.

So do you think implementing GradientContour makes sense for hplot then? Any thoughts on what the struct would look like?

rigelrozanski avatar May 09 '20 03:05 rigelrozanski

interesting paper.

I think it would be better to get the ball rolling on the gonum/plot side first. (and regroup here if that doesn't pan out).

WDYT?

sbinet avatar May 16 '20 16:05 sbinet

ok, I've filed https://github.com/gonum/plot/issues/625 wrt the gradient issue.

sbinet avatar Jun 03 '20 17:06 sbinet