plotly / dash-slicer

A volume slicer for Dash
https://dash.plotly.com/slicer
MIT License
24 stars 8 forks source link

Init volume in a callback #53

Open francoisebouvet opened 3 years ago

francoisebouvet commented 3 years ago

In all the given examples, the volume and the slicer are global variables. It would be useful to be able to declare these variables in a callback. It would allow the user to select the file to vizualize during the session. The code below doesn't work: the slicer are well designed but the images remain completely blank.

  def layout(slicer0, slicer1, slicer2):

    layout = html.Div([
        html.Div(
            [
                html.Center(html.H3("Axial")),
                slicer0.graph,
                html.Br(),
                slicer0.slider,
                *slicer0.stores,
            ]
        ),
        html.Div(
            [
                html.Center(html.H3("Coronal")),
                slicer1.graph,
                html.Br(),
                slicer1.slider,
                *slicer1.stores,
            ]
        ),
        html.Div(
            [
                html.Center(html.H3("Sagittal")),
                slicer2.graph,
                html.Br(),
                slicer2.slider,
                *slicer2.stores,
            ]
        ),
    ],     style={
        "display": "grid",
        "gridTemplateColumns": "50% 50%",
    },
    )
    return layout

app = dash.Dash(
    __name__,
    meta_tags=[{
        "name": "viewport",
        "content": "width=device-width, initial-scale=1"
    }]
)

app.layout = html.Div([
        dbc.Button("Apply", id="display_ct"),
        html.Div(id="frame_ct_display"),
])

@app.callback(
    [Output("frame_ct_display", "children")],
    [Input("display_ct","n_clicks"),]
)
def display_ct(n_clicks):

    if n_clicks is None:
         raise PreventUpdate

    vol = imageio.volread("imageio:stent.npz")
    slicer0 = VolumeSlicer(app, vol, axis=0)
    slicer1 = VolumeSlicer(app, vol, axis=1)
    slicer2 = VolumeSlicer(app, vol, axis=2)

    return [layout(slicer0, slicer1, slicer2)]

if __name__ == '__main__':
    app.run_server(debug=True, dev_tools_props_check=False)
almarklein commented 3 years ago

This is, I think, because the VolumeSlicer creates components that must be known at the time that the application is started.

francoisebouvet commented 3 years ago

If I understand well, it means that the volume must be known before launching the application, in other words, the user can't choose the file he/she wants to visualize. This narrows the usefullness of VolumeSlicer.

almarklein commented 3 years ago

in other words, the user can't choose the file he/she wants to visualize.

Well, that's up for the developer. You can certainly make it that way, e.g. by creating multiple slicers beforehand, and only showing one at a time. That may not be perfect, but I think this is a more a limitation of Dash, or just the fact that this a server-client architecture.

francoisebouvet commented 3 years ago

With Dash, I am able to choose the image I want to visualize and to change it during the session. So I don't think that it is a limitation of Dash.

fracarfer5 commented 3 years ago

Actually, I'm having the same problem as @francoisebouvet , I'm not able to update the data through a callback because the user needs to choose the file when the application is running. It would be nice to be possible to have this feature. I'm trying to do it with the create_overlay_data feature, however with unsuccessful results yet. I hope to get it soon. :(