简体   繁体   中英

Using complex numpy arrays with DCC.Store component (Dash/Python)

so I am working with relatively large arrays (size (13, 8192)) to plot some Figures on a website. It has already been implemented like this, so changes are difficult to make.

As I am running out of memory using the local storage of the browser, I have to use directly a given complex NumPy array and then split it into the real and imaginary parts in another Callback. The problem is that I can't JSON serialize complex-like arrays. Does someone know what can I do to "save" this sort of array using the dcc.Store component of Dash? Thanks in advance.

Here is an example of the code (it is a really short version of it).

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output


import plotly.graph_objects as go  
import numpy as np

app = dash.Dash(__name__)


T0 = 1E-12 # duration of input 
N = 8192 #ammount of points 
dt = 750*T0/N 
T = np.arange(-N/2, N/2)*dt
m = 1 
C = 0 


def envelopef(T,T0,C,m):
    U = (np.exp(-((1+1j*C)/2)*((T/T0)**(2*m)))).astype(complex) 
    UI = np.absolute(U)**2
    return U, UI

z = np.arange(-10,10)
U, UI = envelopef(T,T0,C,m)

scatter1 = go.Scatter(x=T/T0,y=UI)
    
figure1 = go.Figure(data=[scatter1]).update_layout( )

env_graph = dcc.Graph(id='envelopesss', 
                        animate=True,
                        figure=figure1.update_layout(width=600, height=600,
                                                    xaxis = dict(range = [-8, 8])))  

M_slider = dcc.Slider(
        id='m_slider',
        min=1,
        max=10,
        step=1,
        value=m,
        marks={
        1: {'label': '1'},
        10: {'label': '10'}},
    )

app.layout = html.Div([
    M_slider,
    dcc.Store(id='session', storage_type='local'),
     dcc.Loading(id="loading1",children=[html.Div([env_graph]) ],type="circle",),
])





@app.callback(
    Output("loading1", "children"), 
    Output("session", "data"),
    [Input("m_slider", "value")])
def update_bar_chart(mn):
    U, UI = envelopef(T,T0,C,mn)
    phase = np.angle(U)

    scatter1 = go.Scatter(x=T/T0,y=UI)
    
    figure1 = go.Figure(data=[scatter1]).update_layout(width=600, height=600,
                                                    xaxis = dict(range = [-8, 8])) 
    data = {'u': U , 'ui':UI, 'up': phase}

    env_graph = dcc.Graph(figure=figure1)  
    return env_graph, data

app.run_server(debug=True)

You might want to take a look at the ServersideOutput component from dash-extensions . It keeps the data server side (which should improve the performance of your app), and since the default serializer is pickle, complex-valued arrays work out of the box. You can install it via pip,

pip install dash-extensions==0.0.66

To enable use of serverside outputs, replace the app initialization code by

from dash_extensions.enrich import DashProxy, html, dcc, Input, Output, ServersideOutput, ServersideOutputTransform

app = DashProxy(__name__, transforms=[ServersideOutputTransform()])

Next, replace the Output by a ServersideOutput ,

@app.callback(
    Output("loading1", "children"),
    ServersideOutput("session", "data"),
    [Input("m_slider", "value")])

That's it. Your app should now work. For completeness, here is the full app code,

import plotly.graph_objects as go
import numpy as np

from dash_extensions.enrich import DashProxy, html, dcc, Input, Output, ServersideOutput, ServersideOutputTransform

app = DashProxy(__name__, transforms=[ServersideOutputTransform()])

T0 = 1E-12  # duration of input
N = 8192  # ammount of points
dt = 750 * T0 / N
T = np.arange(-N / 2, N / 2) * dt
m = 1
C = 0


def envelopef(T, T0, C, m):
    U = (np.exp(-((1 + 1j * C) / 2) * ((T / T0) ** (2 * m)))).astype(complex)
    UI = np.absolute(U) ** 2
    return U, UI


z = np.arange(-10, 10)
U, UI = envelopef(T, T0, C, m)
scatter1 = go.Scatter(x=T / T0, y=UI)
figure1 = go.Figure(data=[scatter1]).update_layout()
env_graph = dcc.Graph(id='envelopesss',
                      animate=True,
                      figure=figure1.update_layout(width=600, height=600,
                                                   xaxis=dict(range=[-8, 8])))

M_slider = dcc.Slider(
    id='m_slider',
    min=1,
    max=10,
    step=1,
    value=m,
    marks={
        1: {'label': '1'},
        10: {'label': '10'}},
)

app.layout = html.Div([
    M_slider,
    dcc.Store(id='session', storage_type='local'),
    dcc.Loading(id="loading1", children=[html.Div([env_graph])], type="circle", ),
])


@app.callback(
    Output("loading1", "children"),
    ServersideOutput("session", "data"),
    [Input("m_slider", "value")])
def update_bar_chart(mn):
    U, UI = envelopef(T, T0, C, mn)
    phase = np.angle(U)
    scatter1 = go.Scatter(x=T / T0, y=UI)
    figure1 = go.Figure(data=[scatter1]).update_layout(width=600, height=600,
                                                       xaxis=dict(range=[-8, 8]))
    data = {'u': U, 'ui': UI, 'up': phase}
    env_graph = dcc.Graph(figure=figure1)
    return env_graph, data


app.run_server(port=7777)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM