Pass data from View of Django to Dash App

So i’m trying to send to my dash app a full path of csv file and i created a function to get the path and now i’m having trouble on how to send the path to my app.
My first idea would be to send a full dataframe if possible but if that’s not possible at least i want to send the path of the file to my app

VIEWS.PY


def get_file(runsample):

    runsample = runsample
    sample = runsample.sample
    run_name = runsample.rundata.name
    barcode = runsample.barcode
    sample_folder = sample.get_sample_path()

    depth_path = None

    identifiers_list = [barcode, run_name]
    sample_files = [file for file in os.listdir(sample_folder) if all(identifiers in file for
                                                                                identifiers in identifiers_list)]

    for file in sample_files:
        if file.endswith('_basedepth.csv'):
            depth_path = os.path.join(sample_folder, file)
    
    return depth_path
    




def dashboa(requests, **kwargs):
    context = {}
    id_ = kwargs.get('pk')
    barcode_ = kwargs.get('barcode')
    rundata = get_object_or_404(models.RunData, run_id=id_)
    runsample = get_object_or_404(models.RunSampleData, rundata=rundata, barcode=barcode_)
    file_path = get_file(runsample)
    df = pd.read_csv (file_path) 
    context['dash_context'] = {"dataframe":{'value':file_path}}

    return render(requests,'runs/dash.html', context)

DASH.HTML


{%load plotly_dash%}


    
{%plotly_app name="dash_app" initial_arguments=dash_context ratio=1 %}

DASH_APP.py



import dash_bootstrap_components as dbc
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import json
from django_plotly_dash import DjangoDash

app =  DjangoDash(name='dash_app',suppress_callback_exceptions=True, external_stylesheets=[dbc.themes.LUX])


df = pd.read_csv('HD40755__IonXpress_009__Auto_user_GSS5-0407-124-CHIP1_03022022_393_333__basedepth.csv', header=None)

df.columns = ["Chromossome", "Region", "Coverage"]
df=df.sort_values(by=['Region'])

dfR=pd.read_csv('ampliconsRightChr.csv')
dfR.columns = ["Chromossome", "Initial Position", "Final Position", 'coverage_mean','coverage_min','coverage_max']

dfgene=pd.read_csv('GenePosition.csv')
dfgene = dfgene.sort_values('Initial_Position', ascending=True).drop_duplicates('Gene')
dfgene['Chromossome'] = 'chr' + dfgene['Chromossome'].astype(str)



def plus1(dataframe):
    data = []
    for index, row in dataframe.iterrows():
        data.append([row['Chromossome'] ,row['Initial Position'] + 1, row['Final Position'] + 1])
    df = pd.DataFrame(data)
    df.columns = ["Chromossome", "Initial Position", "Final Position"]
    return(df)

def minus1(dataframe):
    data = []
    for index, row in dataframe.iterrows():
        data.append([row['Chromossome'] ,row['Initial Position'] - 1, row['Final Position'] - 1])
    df = pd.DataFrame(data)
    df.columns = ["Chromossome", "Initial Position", "Final Position"]
    return(df)

def margeDF (minus1,plus1, df1, dfbed):
    df2 = plus1(df1)
    df3 = minus1(df1)
    df3 = df3.melt(id_vars=["Chromossome"],  
        value_name="Region")
    df3 = df3[['Chromossome','Region']]
    df3['Chromossome'] = 'chr' + df3['Chromossome'].astype(str)
    df2 = df2.melt(id_vars=["Chromossome"],  
        value_name="Region")
    df2 = df2[['Chromossome','Region']]
    df2['Chromossome'] = 'chr' + df2['Chromossome'].astype(str)
    frames = [df2, df3]
    result = pd.concat(frames)
    frames2 = [result, dfbed]
    result2 = pd.concat(frames2)
    result2 = result2.reset_index(drop=True).fillna(0).sort_values(by=['Region']) 
    return result2

lastdf = margeDF(minus1,plus1, dfR, df)           
lastdf = lastdf.sort_values('Coverage', ascending=False).drop_duplicates('Region').sort_index()
lastdf = lastdf.sort_values(by=['Region']) 

app.layout = html.Div(id = 'parent', children = [
        html.Span(html.H1(id = 'H1', children = 'coverage', style = {'textAlign':'center','marginTop':80,'marginBottom':80}), className="border rounded"),
        dbc.NavbarSimple(children=[
        html.Div(style={'display': 'inline-block', 'vertical-align': 'top', 'margin-right': '5vw'},children=[
            html.H4("Please select the Gene", style={'color':"white"}),
            dcc.Dropdown(
            options=[{'label': c, 'value': c} for c in sorted(dfgene['Gene'].unique())],
            optionHeight=35,                                                                            
            searchable=True,                    
            search_value='',                    
            placeholder='Please select the Gene...',     
            clearable=True,                     
            style={'width':"100%"},  id='dropdownGene'),
        ]),

        html.Div(style={'display': 'inline-block', 'vertical-align': 'top'},className='row',children=[
        html.H4("", style={}),
        html.H5(id='chromossome-data', style={'color':"white", 'margin-right': '2em', 'marginTop':60})
        ]),
        html.Div(style={'display': 'inline-block', 'vertical-align': 'top'},className='row',children=[
                html.H4("Please select the Region", style={'margin-right': '2em', 'color':"white"}),
                dcc.Input(
                    id="initial", type="number",style={'marginRight':'5px','display': 'flex', 'float':'left'},
                ),
                dcc.Input(
                    id="end", type="number",style={'marginRight':'5px', 'display': 'flex', 'float':'left'},
                ),
            ]),
        html.Div(style={'display': 'inline-block', 'vertical-align': 'top'},children=[
                html.H4("Last Zoomed in Region is:", style={'color':"white", 'margin-left': '2em'}),
                html.H5(id='relayout-data', style={'color':"white", 'margin-left': '2em'})
                ]),
            ],
            sticky="top",
            color="dark",
            dark=True,
            style={'height': '10.5rem', 'display': 'flex'}
            ),
        html.Div(style={},children=[
            dcc.Graph(id = 'spec_coverage')
        ]),
        ])


# graph_layout = html.Div(style={},children=[
#             dcc.Graph(id = 'spec_coverage')
#         ])
# @app.callback(
#     Output('dataframe', 'children'),
#     Input('dataframe', 'value'))

# # def check_dash_context(dataframe):
# #     print(dataframe)
# #     return html.Div([
# #             '{}..o.i.io.'.format(dataframe),
# #         ])


# def callback_c(*args,**kwargs):
#     da = kwargs['dash_app']
#     print(da)
#     return "Args are [%s] and kwargs are %s" %(",".join(args), kwargs)

@app.callback(
    Output('relayout-data', 'children'),
    [Input('spec_coverage', 'relayoutData'),
    Input('dropdownGene', 'value')])


def display_relayout_data(relayoutData, gene):
    if gene is None:
        relayoutData['xaxis.range[0]']=None
        relayoutData['xaxis.range[1]']=None
        return html.Div([
        '',
    ])
    elif relayoutData is not None:
        lastdff = dfgene[dfgene.Gene == gene]
        chr = lastdff['Chromossome'].values[0]
        x0 = relayoutData['xaxis.range[0]']
        x0 = int(x0)
        x1 = relayoutData['xaxis.range[1]']
        x1 = int(x1)
        return html.Div([
            '{}:{}-{}'.format(chr,x0,x1),
        ])


# @app.callback(
#     Output('dropdownGene', 'options'),
#     Input('dropdown', 'value')
# )
# def set_Gene_options(chromossome):
#     lastdff = dfgene[dfgene.Chromossome == chromossome]
#     #print(lastdff)
#     return [c for c in sorted(lastdff['Gene'].unique())]

@app.callback(
    [Output('initial', 'value'),
    Output('end', 'value')],
    Input('dropdownGene', 'value')
)

def set_Input_values(gene):
    if gene is None:
        an_integer_initial = None
        an_integer_final = None
        return an_integer_initial,an_integer_final
    else:
        lastdff = dfgene[dfgene.Gene == gene]
        #print(lastdff['Initial_Position'], lastdff['Final_Position'])
        init = lastdff['Initial_Position']
        strings = [str(begs) for begs in init]
        a_string = "". join(strings)
        an_integer_initial = int(a_string)
        # print(an_integer)
        fin = lastdff['Final_Position']
        strings_final = [str(begs) for begs in fin]
        a_string_final = "". join(strings_final)
        an_integer_final = int(a_string_final)
        return an_integer_initial,an_integer_final
# print(an_integer_final)


@app.callback(
    Output('chromossome-data', 'children'),
    Input('dropdownGene', 'value'))


def display_chromossome_data(gene):
    if gene is None:
        return html.Div([
        '',
    ])
    else:
        lastdff = dfgene[dfgene.Gene == gene]
        chr = lastdff['Chromossome'].values[0]
        return html.Div([
            '{}:'.format(chr),
        ])



@app.callback(
    Output('spec_coverage', 'figure'),
    # Input('spec_slider', 'value'),
    # Input('dropdown', 'value'),
    [Input("initial", "value"),
    Input("end", "value"),
    Input('dropdownGene', 'value')])



def plot_data(beg, fin, dropGene):
    dff=lastdf
    dffGene = dfgene[(dfgene['Gene'] == dropGene)]
    GeneInitPOS = dffGene['Initial_Position'].min()
    GeneFinPOS = dffGene['Final_Position'].max()
    dfff=dff[(dff['Region'] >= GeneInitPOS) & (dff['Region'] <= GeneFinPOS)]

    # dff=dfff['Region']>=beg & dfff['Region']<=fin
    dffff=dfff[(dfff['Region'] >= beg) & (dfff['Region'] <= fin)]
    fig2 = go.Figure()
    
    fig2.add_trace(go.Scatter(x=dffff['Region'],y=dffff['Coverage'], fill='tozeroy', name='Coverage'))

    fig2.update_layout(
                      xaxis_title = 'Region',
                      yaxis_title = 'Coverage',
                      )

    # full_fig = fig2.full_figure_for_development()
    # print(full_fig.layout.xaxis.range)   
    return fig2



You’re passing an initial argument called ‘value’ on a component in your dash app called ‘dataframe’, but it is not clear where this component is (is it referenced in the layout function?) and there doesn’t seem to be any callback that uses its value.

In other words, nothing seems to be using your initial value. It is not totally clear to me what ‘having trouble on how to send the path’ means in terms of expected behaviour, but it does sound like it could be related.

So basically where i have

df = pd.read_csv(‘HD40755__IonXpress_009__Auto_user_GSS5-0407-124-CHIP1_03022022_393_333__basedepth.csv’, header=None)

i want the dataframe to be the same as the file_path im trying to pass to my pass but i’m not sure what i’m doing wrong with the context

It is not clear which part of the dash app (ie which property of which component) you are trying to store the file path on.

Each callback takes in as arguments a specified list of these component properties. To pass the file path, you will need a component, possibly hidden in the display, that holds this information. At the moment you’re trying to use a component called ‘dataframe’ which doesn’t seem to feature in your app.layout function.

how do i do it if i want pass my filepath to a div?

this were the changes i made but then i got an error in the command line saying

Internal Server Error: /django_plotly_dash/app/dash_app/initial/dpd-initial-args-f576ee5248bc4c41a5a6c09b5bdae526/_dash-update-component

and when i enter the url it says

MESSAGE **http://localhost/django_plotly_dash/app/dash_app/initial/dpd-initial-args-51f68c6cb36d4799a3c5b50fd4d922ad/_dash-update-component** JSONDecodeError('Expecting value: line 1 column 1 (char 0)') ````Traceback (most recent call last): File "/miniconda/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/miniconda/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "/miniconda/lib/python3.8/site-packages/django_plotly_dash/views.py", line 74, in update return _update(request, ident, stateless, **kwargs) File "/miniconda/lib/python3.8/site-packages/django_plotly_dash/views.py", line 82, in _update request_body = json.loads(request.body.decode('utf-8')) File "/miniconda/lib/python3.8/json/__init__.py", line 357, in loads return _default_decoder.decode(s) File "/miniconda/lib/python3.8/json/decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/miniconda/lib/python3.8/json/decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) ````

def dashboa(requests, **kwargs):
    id_ = kwargs.get('pk')
    barcode_ = kwargs.get('barcode')
    rundata = get_object_or_404(models.RunData, run_id=id_)
    runsample = get_object_or_404(models.RunSampleData, rundata=rundata, barcode=barcode_)
    file_path = get_file(runsample)

    df = pd.read_csv (file_path) 
    context={}
    context = {"dash_context": {'bed_file_path':"{file_path}"}}
    
    return render(requests,'runs/dash.html', context=context)


{%load plotly_dash%}


{% block content %}


  
{%plotly_app name="dash_app" initial_arguments=dash_context ratio=1 %}
{% endblock %}

app.layout = html.Div(id = 'parent', children = [
        html.Span(html.H1(id = 'H1', children = 'coverage', style = {'textAlign':'center','marginTop':80,'marginBottom':80}), className="border rounded"),
        html.Div(id='bed_file_path'),
        dbc.NavbarSimple(children=[
        html.Div(style={'display': 'inline-block', 'vertical-align': 'top', 'margin-right': '5vw'},children=[
            html.H4("Please select the Gene", style={'color':"white"}),
            dcc.Dropdown(
            options=[{'label': c, 'value': c} for c in sorted(dfgene['Gene'].unique())],
            optionHeight=35,                                                                            
            searchable=True,                    
            search_value='',                    
            placeholder='Please select the Gene...',     
            clearable=True,                     
            style={'width':"100%"},  id='dropdownGene'),
        ]),

        html.Div(style={'display': 'inline-block', 'vertical-align': 'top'},className='row',children=[
        html.H4("", style={}),
        html.H5(id='chromossome-data', style={'color':"white", 'margin-right': '2em', 'marginTop':60})
        ]),
        html.Div(style={'display': 'inline-block', 'vertical-align': 'top'},className='row',children=[
                html.H4("Please select the Region", style={'margin-right': '2em', 'color':"white"}),
                dcc.Input(
                    id="initial", type="number",style={'marginRight':'5px','display': 'flex', 'float':'left'},
                ),
                dcc.Input(
                    id="end", type="number",style={'marginRight':'5px', 'display': 'flex', 'float':'left'},
                ),
            ]),
        html.Div(style={'display': 'inline-block', 'vertical-align': 'top'},children=[
                html.H4("Last Zoomed in Region is:", style={'color':"white", 'margin-left': '2em'}),
                html.H5(id='relayout-data', style={'color':"white", 'margin-left': '2em'})
                ]),
            ],
            sticky="top",
            color="dark",
            dark=True,
            style={'height': '10.5rem', 'display': 'flex'}
            ),
        html.Div(style={},children=[
            dcc.Graph(id = 'spec_coverage'),
        ]),
        ])

Your error is unreadable, but its probably due to not setting some property on this div.

Try something like context = {"dash_context": {"bed_file_path": {"children": file_path}}}

Adding style=dict(display="none") to this component in the layout call will hide its contents, but that is something to do once you have this working.

1 Like

Thank you so much, your solution worked like a charm. I was not understanding the problem until you wrote this last reply.

i just have one final question, can i pass trough a full dataframe to dash trough context?

Probably not a good idea, as these values will get passed to and from the client. Better to pass some sort of token, like your path, and then map that to the dataframe in the server. If getting that dataframe is expensive then caching is going to be your friend here.

1 Like

and can i access for example the path u just helped me with outside of the layout?

Yes, its just a value. I find something like a slug (for finding a particular model instance) or a cache key (for other things like dataframes) are good candidates for the value in the layout - small, and html/js friendly strings.

Django has lots of functionality, like sessions, caching etc, to help you here.