Dear community,
I have a added to an iFrame component, which holds a GLViewer object. The script captures all transformations of the GLViewer. Now my goal ist to access this transformation in my dash application. Is there an easy way to save the data to a dcc.store? Or is there a better way to access the data within dash?
Thanks in advance!
Hi @xderes
Welcome to the community. That’s an interesting question.
Can you please provide us with a minimal working example with the Iframe and the GLViewer?
Please see the following code. My goal is that the GLViewer keeps the current transformation and updated just the molecule structure. Right now the transformation gets reseted at every button click. My initial idea was to save the transformation after each update in a store but I don’t know how to access the store from a custom html script as it is in the bottom of the MolTo3DView function, which logs to the console right now (just at each click right now and not after each change of the trafo).
Is there an easier way which I couldn’t see? Or would this be the way to go?
import dash
from dash import Dash, dcc, html
from rdkit import Chem
from rdkit.Chem import AllChem
from dash.dependencies import Input, Output, MATCH, ALL
import time
import py3Dmol
app = Dash(__name__)
def MolTo3DView(smi):
mol = Chem.MolFromSmiles(smi)
mol = Chem.AddHs(mol)
AllChem.EmbedMolecule(mol)
AllChem.MMFFOptimizeMolecule(mol, maxIters=200)
mblock = Chem.MolToMolBlock(mol)
view = py3Dmol.view(width=300, height=300)
view.addModel(mblock, 'mol')
view.setStyle({'stick':{}})
view.zoomTo()
view.uniqueid = str(time.time_ns())
return '''<html style="overflow: hidden; height: 100%; width: 100%"> \
<head>
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
"use strict";
let myview
$(window).load(() => {
document.getElementById("undefined").addEventListener("click", () => console.log( viewer_''' + view.uniqueid + '''.getView()))
})
</script>
</head>
<body style="height: 100%; width: 100%">''' + view._make_html() + '</body></html>'
app.layout = html.Div([
html.Button('CC', id={'type':'mol', 'index':'0'}),
html.Button('CCo', id={'type':'mol', 'index':'1'}),
html.Iframe(
srcDoc=MolTo3DView('CC'), id='molView', style={'width': '400px', 'height': '400px'}
),
])
# updated the iframe but resets the transformation always.
@app.callback(
Output('molView', 'srcDoc'),
Input({'type': 'mol', 'index': ALL}, 'n_clicks'),
prevent_initial_call=True
)
def callback(el_id):
ctx = dash.callback_context
if ctx.triggered_id['index'] == 1:
return MolTo3DView('CCCC')
else:
return MolTo3DView('CC')
if __name__ == '__main__':
app.run_server(debug=True)
Thanks alot for your help and I hope this is a well stated mwe!