过去几天来,我第一次与Plotly和Dash交往,希望为地理NetCDF4数据开发基于浏览器的数据浏览器。到目前为止,它的简单性给我留下了深刻的印象,但是我发现与choroplethmapbox
的某些交互花费的时间比预期的要长。我相信这可能是与here
以下内容是指here中可用的代码和示例数据,其中可以使用以下命令运行Dash应用程序:
python choropleth.py
(Python 3.7)。
我的数据来源来自一个具有时间,深度,纬度和经度尺寸的4D NetCDF4文件(在本例中为海洋温度模型-temp.nc)。就我而言,我仅绘制2D氯体积图,但我希望用户也可以交互选择所需的时间间隔(并最终选择深度)(渲染将始终在2D空间中)。
使用here中的示例,我使用2D网格单元的GeoJSON文件与Pandas DataFrame结合来渲染海洋温度。一切都按预期工作,但是滑块值(时间)的任何更改都需要很长时间才能更新(在我的计算机上大约为六秒钟)。在选择滑块值和运行update_figure()
回调之间似乎有大约一秒钟的时间,然后在浏览器中开始新渲染之前又需要4-5秒。
update_figure()
回调直接从NetCDF4文件读取请求的数据,然后直接更新现有图形字典中的Z值并将其作为新图形返回(请参见下面的代码片段)。最初,我担心响应时间较慢是由于从NetCDF4读取数据,但是基本的计时功能显示,update_figure()
回调在大多数情况下的运行时间不到0.01秒。看来延迟是来自@app.callback
还是Dash中的渲染功能(发布update_figure()
)?
# Create the callback and callback function (update_figure)
@app.callback(Output('plot', 'figure'),
[Input('slide', 'value')],
[State('plot','relayoutData'),State('plot', 'figure')])
def update_figure(x,r,f):
t0 = tme.time()
f['layout']['mapbox']['center']['lat'] = f['layout']['mapbox']['center']['lat']
f['layout']['mapbox']['center']['lon'] = f['layout']['mapbox']['center']['lon']
f['layout']['mapbox']['zoom'] = f['layout']['mapbox']['zoom']
# If the map window has been panned or zoomed, grab those values for the new figure
if r is not None:
if 'mapbox.center' in r:
f['layout']['mapbox']['center']['lat'] = r['mapbox.center']['lat']
f['layout']['mapbox']['center']['lon'] = r['mapbox.center']['lon']
f['layout']['mapbox']['zoom'] = r['mapbox.zoom']
# Extract the new time values from the NetCDF file
tmp = nc['temp'][x, -1, :, :].values.flatten()
# Repace the Z values in the original figure with the updated values, leave everything else (e.g. cell geojson and max/min ranges) as-is
f['data'][0]['z'] = np.where(np.isnan(tmp), None, tmp).tolist()
print("update_figure() time: ",tme.time()-t0)
return f
我怀疑缓慢的渲染时间某种程度上与每个单元格多边形的GeoJSON有关(总共渲染了47k网格单元格多边形,每个多边形由6个点定义(即总计284k点)),不幸的是,无法进一步简化。
我正在寻求有关在用户与应用程序交互时如何加快更新/渲染速度的建议。我有两个想法:
choroplethmapbox
是否已经使用WebGL?如果没有,是否有一条途径可以利用它来更快地渲染?建议表示赞赏。