How to define the html Molecule3dviewer component before parsing a PDB file?
I am trying to create a Dash application for a user who uploads some PDB structural files, and a table is displayed showing some features for the molecules mentioned in those PDB files. This worked well. Then I added a Molecule3dviewer component from Dash Bio but that gave me a runtime error “Cannot read properties of undefined (reading ‘length’)”. It is talking about some variable length in the molecule3dviewer Javascript code because I don’t have any variable called length in my code.
The error’s full message is:
"(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)
TypeError: Cannot read properties of undefined (reading 'length')
at Function.value (http://localhost:8050/_dash-component-suites/dash_bio/async-moleculeviewer3.v1_0_2m1647653451.js:1:2631)
at t.value (http://localhost:8050/_dash-component-suites/dash_bio/async-moleculeviewer3.v1_0_2m1647653451.js:1:3905)
at t.value (http://localhost:8050/_dash-component-suites/dash_bio/async-moleculeviewer3.v1_0_2m1647653451.js:1:3821)
at commitLifeCycles (http://localhost:8050/_dash-component-suites/dash/deps/react-dom@16.v2_18_2m1735904342.14.0.js:19970:24)
at commitLayoutEffects (http://localhost:8050/_dash-component-suites/dash/deps/react-dom@16.v2_18_2m1735904342.14.0.js:22938:9)
at HTMLUnknownElement.callCallback (http://localhost:8050/_dash-component-suites/dash/deps/react-dom@16.v2_18_2m1735904342.14.0.js:182:16)
at Object.invokeGuardedCallbackDev (http://localhost:8050/_dash-component-suites/dash/deps/react-dom@16.v2_18_2m1735904342.14.0.js:231:18)
at invokeGuardedCallback (http://localhost:8050/_dash-component-suites/dash/deps/react-dom@16.v2_18_2m1735904342.14.0.js:286:33)
at commitRootImpl (http://localhost:8050/_dash-component-suites/dash/deps/react-dom@16.v2_18_2m1735904342.14.0.js:22676:11)
at unstable_runWithPriority (http://localhost:8050/_dash-component-suites/dash/deps/react@16.v2_18_2m1735904342.14.0.js:2685:14)"
If I use the sample file they mentioned in the example code here Molecule3dViewer | Dash for Python Documentation | Plotly, it gets displayed correctly. This file is working because here the PDB data is parsed before the html.Div component for molecule3dviewer is defined.
import dash_bio as dashbio
from dash import Dash, html, Input, Output, callback
from dash_bio.utils import PdbParser, create_mol3d_style
app = Dash()
parser = PdbParser('https://git.io/4K8X.pdb')
data = parser.mol3d_data()
styles = create_mol3d_style(
data['atoms'], visualization_type='cartoon', color_element='residue'
)
app.layout = html.Div([
dashbio.Molecule3dViewer(
id='dashbio-default-molecule3d',
modelData=data,
styles=styles
),
"Selection data",
html.Hr(),
html.Div(id='default-molecule3d-output')
])
But I want to define the html.Div component first and then the PDB filename will be selected by the user interaction on my application. This is causing the runtime error because it needs PDB data before the html.Div component is defined. I tried to define a dummy PDB data initially for the html.Div component, and then wrote a callback function that gets triggered by the user selection of a cell from the table. The callback defines the PDB file to be parsed and displayed in the molecule3dviewer. Here is a snippet of the html.Div component:
html.Div([
dashbio.Molecule3dViewer(
id='dashbio-default-molecule3d',
modelData={"atoms": [], "bonds": []}, # Minimal valid placeholder data
styles={}
)
])
Here is a snippet of the callback function:
@app.callback(
Output('dashbio-default-molecule3d', 'modelData'),
Output('dashbio-default-molecule3d', 'styles'),
Input('tbl', 'active_cell'),
State('tbl', 'data'),
prevent_initial_call=True
)
def update_molecule_viewer(active_cell, data):
"""
Update the Molecule3D Viewer based on the selected row in the DataTable.
"""
print("inside update molecule viewer")
row_idx = active_cell.get('row')
mol_id = data[row_idx].get('mol_ID')
mol_data = mapping.get(mol_id)
pdb_file = mol_data.get('pdb')
# Parse the PDB file to get Molecule3D data
try:
pdb_parser = PdbParser(pdb_file)
pdb_data = pdb_parser.mol3d_data()
pdb_styles = create_mol3d_style(pdb_data['atoms'], visualization_type='cartoon', color_element='residue')
# data for dashbio molecule3d viewer
return pdb_data, pdb_styles
except Exception as e:
return f"Error parsing PDB file: {e}"
It is not showing any error, just printing “inside update molecule viewer” so the callback is getting triggered but not displaying the 3D molecule structure. It is giving the runtime error mentioned above.
Could anyone please tell me how to define the PDB data after html.Div definition?
Thank you!