Go Plotly

May 11, 2020 • edited May 13, 2020

Let me introduce you to Go Plotly. This module will help you to build valid Plotly json to easily create figures from Go!

plotly

The reasons behind

I’ve been working with Plotly for a long time and I find It really powerful without loosing intuitive usage. The ecosystem is really big and is growing every day.

Every time I needed to create a Plotly figure from Go code, I created a structure matching the Plotly.js expected input and used that to generate the json objects. Although this approach works well, it escalates really poorly and is error prone.

One day, I decided to write a go-plotly package with all this figures that I frequently used to avoid those little differences between different projects that make everything confusing due to different naming on each project or missing fields. The idea was to have a Go structure with all the field for each available figure in Plotly. At this point, I started to read trough the plotly reference and I realised that there was a LOT to be written down. So this approach was easily put aside.

Another day, I was learning about JSON schema and I found that Plotly provided an schema for their plots and was quickly excited for the possibilities. But it turns out that the schema provided by Plotly doesn’t follow the standard JSON schema. In fact, It looks like a custom schema made just for Plotly. Theoretically, It could be possible to read this file and use it from Go to generate figures. But It also looked like a huge task.

I was reading a post about generics in Go where someone proposes to use code generation instead of generics. arguing that code generation was easier to understand and debug in case something went wrong. what if I could use the Plotly schema to generate the structs to hold the figure data? This is something that could be reasonably achieved.

Learning about how to write a blog in Markdown, I discovered Hugo and this Blog was born. During the process, I gained interest about the powerful Go text templating system and read some post of people generating all kind of text data using it. I even found a generics implementation using text templates. so, could I use go templates to generate Go code?

A month ago I got angry about swagger code generators because most of them didn’t generate code that could be updated after a modification in the swagger file and I wonder how hard it could be to generate code from the swagger file. This leaded me to implement a quick tool to parse render go templates based on json input called Plate.

Last but not least, I started a serious project that required real time Plots in frontend. This has been the reason why I collected the will power to start working on go-plotly. I wrote a few templates with Plate and formatted the output with go fmt. Et voila! go-plotly was born.

How it works

All the necessary information is in the readme and you can check the examples section to get an idea of how it works.

Apart from the autogenerated structs, I’ve implemented an small offline package that generates html files with the necessary code to display the images. This allows you to write code like this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import (
    grob "github.com/MetalBlueberry/go-plotly/graph_objects"
    "github.com/MetalBlueberry/go-plotly/offline"
)

func main() {
    fig := &grob.Fig{
        Data: grob.Traces{
            &grob.Bar{
                Type: grob.TraceTypeBar,
                X:    []float64{1, 2, 3},
                Y:    []float64{1, 2, 3},
            },
        },
        Layout: &grob.Layout{
            Title: &grob.LayoutTitle{
                Text: "A Figure Specified By Go Struct",
            },
        },
    }

    offline.Show(fig)
}

Equivalent to python code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import plotly.graph_objects as go
import plotly.io as pio

# Using graph_objects
fig = go.Figure(
    data=[
        go.Bar(
            x=[1, 2, 3],
            y=[1, 2, 3],
        ),
    ],
    layout_title_text= "A Figure Specified By Python Dictionary",
)

pio.show(fig)

# Using dict syntax
fig = dict({
    "data": [
        {
            "type": "bar",
            "x": [1, 2, 3],
            "y": [1, 3, 2]
        }
    ],
    "layout": {
        "title": {
            "text": "A Figure Specified By Python Dictionary"
        }
    }
})

pio.show(fig)

And javascript

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var fig {
    data: [
        {
            type: "bar",
            x: [1, 2, 3],
            y: [1, 3, 2]
        }
    ],
    layout: {
        title: {
            text: "A Figure Specified By Python Dictionary"
        }
    }
}

Plotly.newPlot('myDiv', fig);

Conclusions

This library establishes a good foundation to start other projects related to the plotly ecosystem. I’m thinking use It to create a real time plotting library inspired by Plotly Dash. I will let you know of the progress.

blogGoPlotly

Write code for humans, not for computers

The Clap Button