plotly / Dash.jl

Dash for Julia - A Julia interface to the Dash ecosystem for creating analytic web applications in Julia. No JavaScript required.
MIT License
489 stars 40 forks source link

Contributed Examples #50

Open terasakisatoshi opened 4 years ago

terasakisatoshi commented 4 years ago

As well as Interact.jl Contributed Examples https://github.com/JuliaGizmos/Interact.jl/issues/36 , it is good idea to collect examples using Dash.jl.

Here is my example

Code

# Usage: just run this code 
# tested on Julia 1.4 and 1.5 and 1.6-DEV

using Dash
using DashHtmlComponents
using DashCoreComponents
using Plots

function powplot(n)
    p = plot(x -> x^n, label = "y=x^$n", xlims=[0,1])
    figure = (data = Plots.plotly_series(p), layout = Plots.plotly_layout(p))
    figure
end

app =
    dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

app.layout = html_div(style = Dict(:width => "50%")) do
    html_h1("Hello Dash"),
    html_div() do
        html_div("slider", style = (width = "10%", display = "inline-block")),
        html_div(dcc_slider(
            id = "slider",
            min = 0,
            max = 9,
            marks = Dict(i => "$i" for i = 0:9),
            value = 1,
        ),style = (width = "70%", display = "inline-block"))
    end,
    html_br(),
    dcc_graph(id = "power", figure = powplot(1))
end

callback!(app, Output("power", "figure"), Input("slider", "value")) do value
    powplot(value)
end

run_server(app)

Result

powslider

Updated 2022/3/5

It seems the current Dash.jl does not work the example above. I've fixed the example as below:

using Dash
using PlotlyJS

#      Status `~/.julia/environments/v1.7/Project.toml`
#  [1b08a953] Dash v1.1.2

function powplot(n)
    x = 0:0.01:1
    y = x .^ n
    p = plot(x, y, mode="lines")
    p.plot 
end

app =
    dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

app.layout = html_div(style = Dict(:width => "50%")) do
    html_h1("Hello Dash"),
    html_div() do
        html_div("slider", style = (width = "10%", display = "inline-block")),
        html_div(dcc_slider(
            id = "slider",
            min = 0,
            max = 9,
            marks = Dict(i => "$i" for i = 0:9),
            value = 1,
        ),style = (width = "70%", display = "inline-block"))
    end,
    html_br(),
    dcc_graph(id = "power", figure = powplot(1))
end

callback!(app, Output("power", "figure"), Input("slider", "value")) do value
    powplot(value)
end

run_server(app)
waralex commented 4 years ago

Yes, this is a great idea, thank you! I have a repository https://github.com/waralex/DashboardsExamples with examples using Dashboards (the progenitor of Dash). I think that after the release of the first version of Dash, I will rewrite all the examples in it using Dash. Maybe after that I will move it out of my github to plotly. @alexcjohnson , what do you think?

terasakisatoshi commented 4 years ago

Hi @waralex , good to know there are lots of examples !!!

I have a repository https://github.com/waralex/DashboardsExamples with examples using Dashboards (the progenitor of Dash).

Here is a more complicated example using PlotlyJS.jl instead of Plots.jl.

Code

# sphere.jl

using Dash
using DashHtmlComponents
using DashCoreComponents

using PlotlyJS

function drawsphere(r, N, camera)
    traces = typeof(scatter3d())[]
    φ = range(0.0, 2π, length = N)
    for θ in range(0, 2π, length = N)
        x = @. r * sin(θ) * cos(φ)
        y = @. r * sin(θ) * sin(φ)
        z = repeat([r * cos(θ)], N)
        push!(
            traces,
            scatter3d(
                x = x,
                y = y,
                z = z,
                showlegend = false,
                mode = "markers",
                marker = attr(color = :blue),
            ),
        )
    end
    layout = Layout(scene = attr(camera = camera))
    p = plot(traces, layout)
    figure =
        (data = getfield.(p.plot.data, :fields), layout = p.plot.layout.fields)
    figure
end

INIT_CAMERA_ATTR = attr(
    up = attr(x = 0, y = 0, z = 1),
    center = attr(x = 0, y = 0, z = 0),
    eye = attr(x = 1.25, y = 1.25, z = 1.25),
    projection = attr(type = "projective"),
)

# Application
app =
    dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

# Create Custom Widget
function create_slider(name; value = 0, min = 0, max = 1, step = 0.1)
    return html_div() do
        html_div(
            name,
            style = (width = "20%", display = "inline-block", padding = "2px"),
        ),
        html_div(
            min,
            style = (width = "5%", display = "inline-block", padding = "2px"),
        ),
        html_div(
            dcc_slider(
                id = name,
                min = min,
                max = max,
                step = step,
                value = value,
            ),
            style = (width = "60%", display = "inline-block"),
        ),
        html_div(
            max,
            style = (width = "5%", display = "inline-block", padding = "2px"),
        )
    end
end

md_string = """
  # Dash.jl

  - Dash for Julia - A Julia interface to the Dash ecosystem for creating analytic web applications in Julia.
  No JavaScript required.
  - This example shows how to control camera of PlotlyJS's object.
  See [JavaScript Figure Reference: layout.scene](https://plotly.com/javascript/reference/layout/scene/#layout-scene-camera) for more details. Enjoy Julia with Dash.jl !!!
  """

# Layout
app.layout = html_div() do
    dcc_markdown(md_string),
    html_h3("up"),
    html_div() do
        html_div(style = (width = "70%",)) do
            create_slider("x_up"),
            create_slider("y_up"),
            create_slider("z_up", value = 1)
        end
    end,
    html_h3("center"),
    html_div() do
        html_div(style = (width = "70%",)) do
            create_slider("x_center"),
            create_slider("y_center"),
            create_slider("z_center")
        end
    end,
    html_h3("eye"),
    html_div() do
        html_div(style = (width = "70%",)) do
            create_slider("x_eye", value = 1.25, max = 2),
            create_slider("y_eye", value = 1.25, max = 2),
            create_slider("z_eye", value = 1.25, max = 2)
        end
    end,
    dcc_graph(id = "sphere", figure = drawsphere(2.0, 20, INIT_CAMERA_ATTR))
end

callback!(
    app,
    Output("sphere", "figure"),
    [
        Input("x_up", "value"),
        Input("y_up", "value"),
        Input("z_up", "value"),
        Input("x_center", "value"),
        Input("y_center", "value"),
        Input("z_center", "value"),
        Input("x_eye", "value"),
        Input("y_eye", "value"),
        Input("z_eye", "value"),
    ],
) do up_x, up_y, up_z, center_x, center_y, center_z, eye_x, eye_y, eye_z
    camera = attr(
        up = attr(x = up_x, y = up_y, z = up_z),
        center = attr(x = center_x, y = center_y, z = center_z),
        eye = attr(x = eye_x, y = eye_y, z = eye_z),
        projection = attr(type = "projective"),
    )
    figure = drawsphere(2.0, 20, camera)
    figure
end

run_server(app)

Result

image

Moelf commented 4 years ago

is it correct to say nearly all plots that can be done with Plots.jl + plotly() backend can be plotted in Dash.jl by using Plots.plotly_series, Plots.plotly_layout technique?

terasakisatoshi commented 4 years ago

In the examples I've tried, it works. Not sure "all" can do 😅

terasakisatoshi commented 4 years ago

I've found If we would like to display image, we can't use Plots.plotly_series technique. Here is a workaround that uses DashHtmlComponents.html_div(src=...). (However, it is not accurate for some images due to a kind of TypeError.)

Code

# imageviewer.jl

using Base64

using Dash
using DashCoreComponents
using DashHtmlComponents
using ImageShow
using Plots
using TestImages

const remotefiles = [
    "autumn_leaves.png" ,
    "blobs.gif" ,
    "cameraman.tif" ,
    "earth_apollo17.jpg" ,
    "fabio_color_256.png" ,
    "fabio_color_512.png" ,
    "fabio_gray_256.png" ,
    "fabio_gray_512.png" ,
    "hela-cells.tif" ,
    "house.tif" ,
    "jetplane.tif" ,
    "lake_color.tif" ,
    "lake_gray.tif" ,
    "lena_color_256.tif" ,
    "lena_color_512.tif" ,
    "lena_gray_256.tif" ,
    "lena_gray_512.tif" ,
    "lena_gray_16bit.png" ,
    "livingroom.tif" ,
    "lighthouse.png" ,
    "mandril_color.tif" ,
    "mandril_gray.tif" ,
    "mandrill.tiff" ,
    "m51.tif" ,
    "moonsurface.tiff" ,
    "mountainstream.png" ,
    "mri-stack.tif" ,
    "multi-channel-time-series.ome.tif" ,
    "peppers_color.tif" ,
    "peppers_gray.tif" ,
    "pirate.tif" ,
    "toucan.png" ,
    "walkbridge.tif" ,
    "woman_blonde.tif" ,
    "woman_darkhair.tif" ,
]

function encode(io::IOBuffer, img)
    io2=IOBuffer()
    b64pipe=Base64EncodePipe(io2)
    write(io,"data:image/png;base64,")
    show(b64pipe, MIME"image/png"(), img) # will be valid if we load ImageShow.jl
    write(io, read(seekstart(io2)))
end

function encode(file::AbstractString)
    img = testimage(file)
    io = IOBuffer()
    encode(io, img)
    String(take!(io))
end

app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

app.layout = html_div() do 
    html_h1("ImageViewer using Dash.jl"),
    dcc_dropdown(
        id = "dropdown",
        options = [(label=f, value=f) for f in remotefiles],
        value = "cameraman.tif",
    ),
    html_img(id="viewer", src=encode("cameraman.tif"))
end

callback!(
    app,
    Output("viewer","src"),
    Input("dropdown","value"),
) do filename
    encode(filename)
end

run_server(app)

Result

goma

terasakisatoshi commented 4 years ago

Check CPU Usage using Dash.jl

Real-time update application using dcc_interval

using Dash
using DashCoreComponents
using DashHtmlComponents

using PyCall

py"""
import psutil
"""

using Plots

const SECOND = 1000
interval = 0.5 * SECOND # msec
xmax = 60
tickstep = Int(xmax / interval * SECOND)
cpu_history = zeros(py"psutil.cpu_count(logical=True)")

app =
    dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

    app.layout = html_div() do
    html_h1("Check CPU Usage using Dash.jl"),
    html_div("Dash.jl: Julia interface for Dash"),
    dcc_graph(id = "example-graph"),
    dcc_interval(
        id="interval-component",
        interval=interval,
        n_intervals=0,
    )
end

callback!(
    app,
    Output("example-graph","figure"),
    [Input("interval-component","n_intervals")],
) do n
    global cpu_history, interval
    percpu = py"psutil.cpu_percent(percpu=True)"
    cpu_history = hcat(cpu_history, percpu)
    cpu_history = cpu_history[begin:end, max(1,end-tickstep+1):end]
    _, len = cpu_history |> size
    p = plot(
        range(1,step=interval/SECOND,length=len),
        cpu_history',
        xlim=[0, xmax],
        ylim=[0, 100],
        label=:none,
        xticks = 0:10:xmax,
        yticks = 0:25:100,
    )
    figure = (data = Plots.plotly_series(p), layout = Plots.plotly_layout(p))
    figure
end

run_server(app, "127.0.0.1", 8050, debug = true)
Screen Shot 2020-08-29 at 13 22 06
PallHaraldsson commented 4 years ago

I like the look of these examples, but they didn't work for me (neither those in the readme), e.g. because of the code stating with the line:

INIT_CAMERA_ATTR = attr(

[..]

ERROR: UndefVarError: attr not defined
Stacktrace:
 [1] top-level scope at REPL[71]:1

I probably have a setup problem but I do neot even find the function here in the repository.

terasakisatoshi commented 4 years ago

@PallHaraldsson Did you install PlotlyJS correctly ? attr is exported by PlotlyJS.

caseykneale commented 3 years ago

Check CPU Usage using Dash.jl

Real-time update application using dcc_interval

Is there anyway to get custom legend labels for this example? IE: Trace 1, Trace 2, Trace 3...? I blew like 2 hrs failing to do so

terasakisatoshi commented 3 years ago

Hi, @caseykneale

How about this code?

    cpu_count = py"psutil.cpu_count(logical=True)"
    label = reshape(["Trace $(c)" for c in 1:cpu_count], 1, cpu_count)
    p = plot(
        range(1,step=interval/SECOND,length=len),
        cpu_history',
        xlim=[0, xmax],
        ylim=[0, 100],
        xticks = 0:10:xmax,
        yticks = 0:25:100,
        label=label,
    )

This will get

image

note that plot function is exported by Plots.jl (not Dash.jl)

This link https://docs.juliaplots.org/latest/tutorial/#Plot-Attributes might help you.

caseykneale commented 3 years ago

Works well thank you! Seems like we still have the issue of PlotlyJS eating plot margins for x and y axis labels. But that's another issue for another day. Thanks you for explaining how to use the Plots.plot rather then the Dash.plot

terasakisatoshi commented 3 years ago

Compare code A and code B

Code

# app.jl
using Dash
using DashHtmlComponents
using DashCoreComponents
using DashBootstrapComponents

using IOCapture
using InteractiveUtils:clipboard

app = dash(external_stylesheets=[dbc_themes.BOOTSTRAP])
# app = dash(external_stylesheets=["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = dbc_container(className="mxy-auto") do
    html_h1("Compare code A with B?"),
    html_div("Put your code before including codeA and codeB"),
    dcc_textarea(
        id="text-code-common",
        placeholder="common code",
        rows=10,
        style=Dict(:width => "100%"),
    ),
    html_div(id="result-common"),
    dbc_row(
        [
            dbc_col(dcc_textarea(
                id="text-codeA",
                placeholder="codeA",
                value="",
                rows=2,
                style=Dict(:width => "100%"),
            )),
            dbc_col(dcc_textarea(
                id="text-codeB",
                placeholder="codeB",
                value="",
                rows=2,
                style=Dict(:width => "100%"),
            ))
        ],
    ),
    dbc_row(
        [
            dbc_col(dbc_button("Compare", id="button-compare", block=true, color="primary", className="margin-auto", size="sm")),
        ],
    ),
    html_h3("Result", style=Dict("text-align" => "center")),
    dbc_row(
        [
            dbc_col(dcc_textarea(
                id="text-resultA",
                placeholder="resultA",
                value="",
                rows=10,
                readOnly=true,
                style=Dict(:width => "100%"),
            )),
            dbc_col(dcc_textarea(
                id="text-resultB",
                placeholder="resultB",
                value="",
                rows=10,
                readOnly=true,
                style=Dict(:width => "100%"),
            ))
        ],
    ),
    dbc_row(
        [
            dbc_col(dbc_button("Copy result A", id="button-copyA", color="primary")),
            dbc_col(dbc_button("Copy result B", id="button-copyB", color="primary")),
        ],
    ),
    html_div("dummy-resultA", id="dummy-resultA", style=Dict("display" => "none")),
    html_div("dummy-resultB", id="dummy-resultB", style=Dict("display" => "none")),
    html_div("dummy-codeA", id="dummy-codeA", style=Dict("display" => "none")),
    html_div("dummy-codeB", id="dummy-codeB", style=Dict("display" => "none"))
end

# Taken from Literate.jl and modified
function sandbox()
    m = Module(gensym())
    # eval(expr) is available in the REPL (i.e. Main) so we emulate that for the sandbox
    Core.eval(m, :(eval(x) = Core.eval($m, x)))
    # modules created with Module() does not have include defined
    # abspath is needed since this will call `include_relative`
    Core.eval(m, :(include(x) = Base.include($m, abspath(x))))
    # load InteractiveUtils
    Core.eval(m, :(using InteractiveUtils))
    return m
end

sb = sandbox()

callback!(
    app,
    [Output("text-resultA", "value"), Output("text-resultB", "value"), Output("result-common", "children")],
    Input("button-compare", "n_clicks"),
    [State("text-codeA", "value"), State("text-codeB", "value"), State("text-code-common", "value")],
) do n_clicks, vA, vB, vCommon
    if isnothing(n_clicks) || n_clicks == 0
        return (nothing, nothing, nothing)
    end

    cCommon = IOCapture.capture(rethrow=Union{}) do
        include_string(sb, vCommon)
    end
    retC = nothing
    if !isnothing(vCommon) && cCommon.error
        retC = """
        $(sprint(showerror, cCommon.value))
        when executing the following code block
        ```julia
        $vCommon
    """
    @warn "$retC"
else
    retC = nothing
end

cA = IOCapture.capture(rethrow=Union{}) do
    include_string(sb, vA)
end
cB = IOCapture.capture(rethrow=Union{}) do
    include_string(sb, vB)
end

if cA.error
    retA = """
    $(sprint(showerror, cA.value))
    when executing the following code block
    ```julia
    $vA
    ```
    """
else
    retA = cA.output
end

if cB.error
    retB = """
    $(sprint(showerror, cB.value))
    when executing the following code block
    ```julia
    $vB
    ```
    """
else
    retB = cB.output
end

return (retA, retB, retC)

end

callback!( app, Output("dummy-resultA", "children"), Input("button-copyA", "n_clicks"), State("text-resultA", "value"), ) do n_clicks, value if !isnothing(n_clicks) && n_clicks > 0 return clipboard(value) end end

callback!( app, Output("dummy-resultB", "children"), Input("button-copyB", "n_clicks"), State("text-resultB", "value"), ) do n_clicks, value if !isnothing(n_clicks) && n_clicks > 0 return clipboard(value) end end

run_server(app, debug=true)


# Usage

- Install `Dash`, `DashCoreComponents`, `DashHtmlComponents`, `DashBootstrapComponents` and `IOCapture`
- `julia app.jl`

# Result

![image](https://user-images.githubusercontent.com/16760547/120929423-eda92480-c723-11eb-9ddf-cc2f539d4c9b.png)

![image](https://user-images.githubusercontent.com/16760547/120929540-6314f500-c724-11eb-853a-e6e24053ef0f.png)

# Edit

Updated at 2022/08/14

```julia
# app.jl
using Dash
using DashBootstrapComponents

using IOCapture
using InteractiveUtils: clipboard

app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP])

app.layout = dbc_container(className = "mxy-auto") do
    html_h1("Compare code A with B?"),
    html_div("Put your code before including codeA and codeB"),
    dcc_textarea(
        id = "text-code-common",
        placeholder = "common code",
        rows = 10,
        style = Dict(:width => "100%"),
    ),
    html_div(id = "result-common"),
    dbc_row([
        dbc_col([
            html_h2("codeA"),
            dcc_textarea(
                id = "text-codeA",
                placeholder = "codeA",
                value = "",
                rows = 2,
                style = Dict(:width => "100%"),
            ),
        ]),
        dbc_col([
            html_h2("codeB"),
            dcc_textarea(
                id = "text-codeB",
                placeholder = "codeB",
                value = "",
                rows = 2,
                style = Dict(:width => "100%"),
            ),
        ]),
    ],),
    dbc_row([
        dbc_col(
            dbc_button(
                "Compare",
                id = "button-compare",
                color = "primary",
                className = "margin-auto",
                size = "sm",
            ),
        ),
    ],),
    html_h3("Result", style = Dict("text-align" => "center")),
    dbc_row([
        dbc_col(
            dcc_textarea(
                id = "text-resultA",
                placeholder = "resultA",
                value = "",
                rows = 10,
                readOnly = true,
                style = Dict(:width => "100%"),
            ),
        ),
        dbc_col(
            dcc_textarea(
                id = "text-resultB",
                placeholder = "resultB",
                value = "",
                rows = 10,
                readOnly = true,
                style = Dict(:width => "100%"),
            ),
        ),
    ],),
    dbc_row([
        dbc_col(dbc_button("Copy result A", id = "button-copyA", color = "primary")),
        dbc_col(dbc_button("Copy result B", id = "button-copyB", color = "primary")),
    ],),
    html_div("dummy-resultA", id = "dummy-resultA", style = Dict("display" => "none")),
    html_div("dummy-resultB", id = "dummy-resultB", style = Dict("display" => "none")),
    html_div("dummy-codeA", id = "dummy-codeA", style = Dict("display" => "none")),
    html_div("dummy-codeB", id = "dummy-codeB", style = Dict("display" => "none"))
end

# Taken from Literate.jl and modified
function sandbox()
    m = Module(gensym())
    # eval(expr) is available in the REPL (i.e. Main) so we emulate that for the sandbox
    Core.eval(m, :(eval(x) = Core.eval($m, x)))
    # modules created with Module() does not have include defined
    # abspath is needed since this will call `include_relative`
    Core.eval(m, :(include(x) = Base.include($m, abspath(x))))
    # load InteractiveUtils
    Core.eval(m, :(using InteractiveUtils))
    return m
end

sb = sandbox()

callback!(
    app,
    [
        Output("text-resultA", "value"),
        Output("text-resultB", "value"),
        Output("result-common", "children"),
    ],
    Input("button-compare", "n_clicks"),
    [
        State("text-codeA", "value"),
        State("text-codeB", "value"),
        State("text-code-common", "value"),
    ],
) do n_clicks, vA, vB, vCommon
    if isnothing(n_clicks) || n_clicks == 0
        return (nothing, nothing, nothing)
    end

    cCommon = IOCapture.capture(rethrow = Union{}) do
        include_string(sb, vCommon)
    end
    retC = nothing
    if !isnothing(vCommon) && cCommon.error
        retC = """
        $(sprint(showerror, cCommon.value))
        when executing the following code block
        ```julia
        $vCommon
    """
    @warn "$retC"
else
    retC = nothing
end

cA = IOCapture.capture(rethrow = Union{}) do
    include_string(sb, vA)
end
cB = IOCapture.capture(rethrow = Union{}) do
    include_string(sb, vB)
end

if cA.error
    retA = """
    $(sprint(showerror, cA.value))
    when executing the following code block
    ```julia
    $vA
    ```
    """
else
    retA = cA.output
end

if cB.error
    retB = """
    $(sprint(showerror, cB.value))
    when executing the following code block
    ```julia
    $vB
    ```
    """
else
    retB = cB.output
end

return (retA, retB, retC)

end

callback!( app, Output("dummy-resultA", "children"), Input("button-copyA", "n_clicks"), State("text-resultA", "value"), ) do n_clicks, value if !isnothing(n_clicks) && n_clicks > 0 return clipboard(value) end end

callback!( app, Output("dummy-resultB", "children"), Input("button-copyB", "n_clicks"), State("text-resultB", "value"), ) do n_clicks, value if !isnothing(n_clicks) && n_clicks > 0 return clipboard(value) end end

run_server(app, debug = true)

john-waczak commented 3 years ago

Is there a way to get the y-axis and the y-ticks to show up?

jorge-jardim commented 3 years ago

Works well thank you! Seems like we still have the issue of PlotlyJS eating plot margins for x and y axis labels. But that's another issue for another day. Thanks you for explaining how to use the Plots.plot rather then the Dash.plot

Is there a way to get the y-axis and the y-ticks to show up?

Im facing the same problem.

terasakisatoshi commented 2 years ago

Hi, I've created a Julia package PyPlotly.jl which is Pythonista friendly Julia user interface for plotly. Now we can write a Julia code as if it is written in Python. Of course we use from Dash.jl !!! Below is an example:

using Dash

using PyPlotly
using JSON3

app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

fig = go.Figure(
    data=[
    go.Bar(x=[1,2,3], y = [4,1,2], name="SF"),
    go.Bar(x = [1,2,3], y = [2,4,5], name="Montréal")
    ],
    layout = go.Layout(title = "Dash Data Visualization"),
)

jsonobj = JSON3.read_json_str(fig.to_json())
data = jsonobj["data"]
layout = jsonobj["layout"]

app.layout = html_div() do
        html_h1("Hello Dash"),
        html_div("PyPlotly.jl: Julia interface for Plotly"),
        dcc_graph(
            id = "example-graph",
            figure = (data=data, layout=layout)
        )
end

run_server(app, "127.0.0.1", 8080)

image

terasakisatoshi commented 2 years ago

@jorge-jardim FYI

using Dash

using PyPlotly
using JSON3
using PyCall

py"""
import psutil
"""

using Plots

const SECOND = 1000
interval = 0.5 * SECOND # msec
xmax = 60
tickstep = Int(xmax / interval * SECOND)
cpu_history = zeros(py"psutil.cpu_count(logical=True)")

app =
    dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

    app.layout = html_div() do
    html_h1("Check CPU Usage using Dash.jl"),
    html_div("Dash.jl: Julia interface for Dash"),
    html_div("PyPlotly.jl: Pythonista friendly Julia interface for Plotly"),
    dcc_graph(id = "example-graph"),
    dcc_interval(
        id="interval-component",
        interval=interval,
        n_intervals=0,
    )
end

callback!(
    app,
    Output("example-graph","figure"),
    [Input("interval-component","n_intervals")],
) do n
    global cpu_history, interval
    percpu = py"psutil.cpu_percent(percpu=True)"
    cpu_history = hcat(cpu_history, percpu)
    cpu_history = cpu_history[begin:end, max(1,end-tickstep+1):end]
    n, len = cpu_history |> size

    xs = range(1,step=interval/SECOND,length=len) |> collect
    ys = Matrix(cpu_history)

    fig=go.Figure()
    for i in 1:n
        fig.add_trace(
            go.Scatter(
                x=xs,
                y=ys[i, :],
                mode="lines",
                name="$i",
            )
        )
    end
    fig.update_xaxes(title_text="Time", range=[1,xmax])
    fig.update_yaxes(title_text="Percent")
    fig.update_layout(
        xaxis = Dict(
            :tickmode => "linear",
            :tick0 => 0.,
            :dtick => 10,
        ),
        yaxis=Dict(
            :tickmode => "linear",
            :tick0 => 0.,
            :dtick => 25,
        )
    )

    jsonobj = JSON3.read_json_str(fig.to_json())
    data = jsonobj["data"]
    layout = jsonobj["layout"]

    figure=(data=data, layout=layout)
    figure
end

run_server(app, "127.0.0.1", 8080)

image

jaboaf commented 1 year ago

nice job everyone. really. i used dash a while back when i was just getting going with data + computers in python and managed to get the hang of it after a little trial and error and really appreciated how far it got me. managed to actually deploy some analytics (essentially statistics in python). moved to julia that summer(2019). was poking around today wondering what the web-app/gui front was like in julia cause, well, the REPL... is the REPL. anyways CLAPS TO YALL for being awesome. i hope to take the julia version of dash for a spin in the next few, will put anything i can muster here. ✌️