go-hep / hep

hep is the mono repository holding all of go-hep.org/x/hep packages and tools
https://go-hep.org
BSD 3-Clause "New" or "Revised" License
231 stars 35 forks source link

idea: hplot band-gradients #701

Open rigelrozanski opened 4 years ago

rigelrozanski commented 4 years ago

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!

sbinet commented 4 years ago

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:

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...)

rigelrozanski commented 4 years ago

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?

sbinet commented 4 years ago

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 commented 4 years ago

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