Developing Julia interface for Plotly Dash

Hi.
I’m new to Julia and I need a single-page interactive dashboard. So I wrote the prototype of Julia interface for Plotly Dash - package Dashboards.jl

Now it has all the basic functionality of Dash - you can create dashboards using dash components from dash_core_components and dash_html_components, and register callbacks for components events.

Simple example:

julia> import HTTP
julia> using Dashboards
julia> app = Dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
    html_div() do
        dcc_input(id = "my-id", value="initial value", type = "text"),
        html_div(id = "my-div")        
    end
end
julia> callback!(app, callid"my-id.value => my-div.children") do input_value
    "You've entered $(input_value)"
end
julia> handler = make_handler(app, debug = true)
julia> HTTP.serve(handler, HTTP.Sockets.localhost, 8080)

You can find more examples in the readme.

Is anyone interested in this functional?

P.S. Sorry, I don’t speak English very well, so if anyone who is interested in this package can correct my mistakes in readme and docs, I will be grateful.

Best regards, Alexandr

30 Likes

Welcome!

Pkg.add(PackageSpec(url="https://github.com/waralex/Dashboards.git"))

dashboards_julians

…now if I knew how to develop Dash Dashboards…
Thanks!

3 Likes

You can use the Plotly Dashboard documentation as a starting point. Key concepts are the same.
I am writing tests now and solving some problems, but I will try to write some examples of dashboards on the weekend if this is interesting for the community

5 Likes

Awesome! Thanks for doing this.

HI Alexandr,

This sounds great, I hope to try this out soon. It’ll help to see some example apps.

Also, have you completelty re-written the python parts of Dash in Julia, or is it calling into python at some point? Looking at the code it seems it is pure Julia, but I wanted to confirm.

Finally, it’ll help if you give us some example of how the python syntax corresponds to the julia syntax when writing Dash applications.

I’m excited to see this.

Regards

Avik

waralex Alexandr,

You have convinced me. I am in.

Let me tell you my motivation. It is to be able to do this

value_a = Slider(0.0,4.0)
Plot(value_a * x^2 + 3.0*x + 7.0,[x,-10.0,10.0])

graphically so I can see the plot change when I move the slider.

Regards
Steven Siew

PS. I can do this in Mathematica

Hi Avik

Yes, Dashboards is an implementation of Dash backend server in pure Julia. In details, I clone Dash repo and components repos at package build stage (because of Pkg don’t work properly with git submodules). At package compilation, I read json files with components meta from this repos and generate Julia functions to create components. make_handler function makes handler for HTTP.serve, which responds to requests of Dash frontend. So I use only JS part from Dash repos

It is pretty simple.

  • component naming: html.Div => html_div, dcc.Graph => dcc_graph and etc
  • component creation: just like in Python, functions for creating components have keywords arguments, which are the same as in Python. html_div(id="my-id", children="Simple text").
    For components that have children prop, two additional signatures are available. (children; kwargs..) and (children_maker::Function; kwargs...) so You can write html_div("Simple text", id="my-id") for simple elements or avoid the hell of nested brackets with do syntax for complex elements:
html_div(id="outer-div") do
    html_h1("Welcome"),
    html_div(id="inner-div") do
    ......
    end
end
  • application and layout:
    python:
app = dash.Dash("Test", external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[....])

Dashboards:

app = Dash("Test", external_stylesheets=external_stylesheets) do
   html_div() do
    ......
   end
end
  • callbacks:
    python:
@app.callback(Output('output', 'children'),
              [Input('submit-button', 'n_clicks')],
              [State('state-1', 'value'),
               State('state-2', 'value')])
def update_output(n_clicks, state1, state2):
.....

Dashboards:

callback!(app, callid"""{state1.value, state2.value} 
                                   submit-button.n_clicks 
                                   => output.children""" ) do state1, state2, n_clicks
.....
end

Be careful - in Dashboards states came first in arguments list

  • json: I use JSON2 for json serialization/deserialization, so in callbacks all json objects are NamedTuples not Dicts. In component props you can use both Dicts and NamedTuples for json objects. But be careful with single property objects: layout = (title = "Test graph") is not interpreted as NamedTuple by Julia - you need add comma at the end layout = (title = "Test graph",)

Hope this is helpful

Best regards, Alexandr

6 Likes

Is this it?

import HTTP
using Dashboards
function make_graph_figure(coeff)
   x_range = -10.0:0.1:10   
   (
       data = [(
           x = x_range,
           y = [coeff * x^2 + 3.0 * x + 7.0 for x in x_range]
       )],
       layout = (title = "$(coeff) * x^2 + 3.0 * x + 7.0",)
   ) 
end
app = Dash("Simple Slider", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]) do
    html_div() do
        html_h1("Slider example"),
        
        dcc_slider(
            id="slider", min=0., max=4., step=0.05, value = 0.,
            updatemode = :drag, tooltip = (always_visible=true,),
            marks = Dict(map(x -> x=>x, 0:4))
        ),                
        dcc_graph(
            id="graph",
            figure = make_graph_figure(0.),
            style = Dict("padding-top" => "20px")
            )
        
                    
    end
end
callback!(app, callid"slider.value => graph.figure") do value
    return make_graph_figure(value)
end
handler = make_handler(app)
HTTP.serve(handler, HTTP.Sockets.localhost, 8080)

11 Likes

Wow it’s awesome! Thanks for your efforts!

Great job tackling this! I have a work Dash dashboard built with our Python connector (we’re a database/analytics company), so it’d be cool to see if it cane be replicated with our Julia connector and your new package.

3 Likes

Offtopic:
I came up with the idea of this package for similar reasons.
I wrote a fast column database for our purposes a few years ago. It stores information about approximately 300 billion events (compressed to 1.5Tb on HDD) and process approximately 3.5K inserts per second. And now we have the problem: we have a large amount of data and we haven’t suitable instruments and workflows for analysis, mining and predictions on that data. So, after thinking, I agreed with the proposal to change the position from developer to analyst. I tried python as an instrument of analysis a little but after c++ its “optimization” upsets me, so I came to Julia (3 weeks ago :slight_smile:)
It’ll help if someone can recommend me good books or courses about data analysis and machine learning in private message. I have good programming and not bad math background and I don’t want to waste time on books where 80% is python syntax description

Sorry for offtopic

Best regards, Alexandr

3 Likes

That’s nice work for 3 weeks time. Thanks for sharing your package!

2 Likes

Hi waralex,

Thanks for the code. That was really amazing.

I think the magic for the graph is in dcc_graph function.

Do you know how to put a label on the slider so that the user would know which slider controls which variable if there are multiple sliders on the web page?

Regards
Steven Siew

You can put html element, div for example near slider.
I’m not a very big specialist in Dash itself. I tried to make a dashboard from examples, I realized that I don’t like doing it on the python, and seeing how it worked, I decided that I could quite easily implement it on Julia (and at the same time get to know Julia better).
You can look at Dash Gallery for an ideas. I plan to implement some of these examples on Julia when I find some time.

1 Like

The magic for the graph is the ReactJS component in the frontend. dcc_graph just generates the correct json with the settings and data for this component

2 Likes

Hi.
I released version 0.2.5 of Dashboards. The main feature is the ability to use PlotlyBase.Plot (or PlotlyJS.Plot) to setup the figure property of the dcc_graph component. Also I implemented most of the dashboards from Dash Tutorial on Dashboards.jl - see DashboardsExamples.

Should I register this version with the General? What do you think?

Best regards, Alexandr

5 Likes

waralex, You should register this with General register, it will make it really easy for newbies to install your package.

So I just wanted to report that it took me couple of hours, going from not knowing any Dash, to implementing a simple interactive app with a handful of widgets. To make it harder, I did not look at the DashboardsExamples repo, just going by the readme and the Dash official docs. So I’m pretty happy with how easy it is to get started with this.

There were a couple of things that I struggled with for a bit

  1. the fact that both sides of the Dict should be Symbols in things like marker
  2. I’m having to ctrl^C the server and then creating a new app object for any change to my application.

It is also worth asking if the do block is the best syntax for describing the heirarchy of widgets. Maybe? But all in all, I’m very happy about how easy this is.

For the record, my code is here: Calculate Pi with Dash · GitHub

and the app looks like this:

9 Likes

Hi, Avik.
Thanks for Your report!

They can also be both strings. These are the requirements of Dash: “marks has the following type: dict with strings as keys and values of type string | dict containing keys ‘label’, ‘style’”. So in marks you can set any Julia structure that marshals to a json dict string : string via JSON2.

I see and think what can be done about it

The do block is most convenient for me, but you also can use the python-like syntax:

 html_div([
           html_span("Pi = "),
           html_span("0.0", id="pi")
          ])

or

html_div(children = [
           html_span("Pi = "),
           html_span("0.0", id="pi")
          ])

I sow you issue in github, but I don’t have time this week (because I need to do some dashboards for my superiors :slight_smile: ) I also sent the registration request to General 3 days ago.

Best regards, Alexandr

4 Likes