molstar / molstar

A comprehensive macromolecular library
https://molstar.org
MIT License
599 stars 140 forks source link

Question: How to visualize docking outputs in embedded HTML? #1098

Open smbatyankh opened 1 month ago

smbatyankh commented 1 month ago

Hello everyone,

I'm reaching out to see if anyone knows how to visualize both protein and ligand interactions. Currently, I've managed to implement two methods for visualizing them in embedded HTML, but I'm still unable to show their interactions clearly. Is there a method to merge structures seamlessly and visualize them within embedded HTML? I'd appreciate any insights or suggestions.

Below is the code I'm currently using for the visualization:

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link rel="icon" href="./favicon.ico" type="image/x-icon">
        <title>Embedded Mol* Viewer</title>
        <style>
            #app {
                display: flex;
                flex-direction: column
                align-items: stretch;
                height: 100vh;
                margin: 0;
                padding: 0;
            }
        </style>
        <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/molstar@latest/build/viewer/molstar.css" />
    </head>
    <body>
        <div id="app"></div>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/molstar@latest/build/viewer/molstar.js"></script>
        <script type="text/javascript">
            molstar.Viewer.create('app', {
                layoutIsExpanded: false,
                layoutShowControls: false,
                layoutShowRemoteState: false,
                layoutShowSequence: true,
                layoutShowLog: false,
                layoutShowLeftPanel: false,

                viewportShowExpand: false,
                viewportShowSelectionMode: true,
                viewportShowAnimation: true,

                pdbProvider: 'rcsb',
                emdbProvider: 'rcsb',
            }).then(viewer => {
            ...
async function loadStructureAndLigand(viewer, mainData, mainFormat, ligands, dataLabel = 'protein') {
    await loadStructureExplicitly(viewer, mainData, mainFormat, dataLabel);

    async function visualizeLigand(data, format, label) {
        const _data = await viewer.plugin.builders.data.rawData({ data: data, label: label });
        const trajectory = await viewer.plugin.builders.structure.parseTrajectory(_data, format);
        const model = await viewer.plugin.builders.structure.createModel(trajectory);
        const structure = await viewer.plugin.builders.structure.createStructure(model);

        const ligandComponent = await viewer.plugin.builders.structure.tryCreateComponentStatic(structure, 'ligand');
        if (ligandComponent) {
            const builder = viewer.plugin.builders.structure.representation;
            const update = viewer.plugin.build();
            builder.buildRepresentation(update, ligandComponent, {
                type: 'ball-and-stick',
                typeParams: { alpha: 1 },
                colorTheme: { name: 'element-symbol' }
            }, { tag: label });
            await update.commit();
        }
    }

    for (let ligand of ligands) {
        await visualizeLigand(ligand.data, ligand.format, ligand.label || 'ligand');
    }
}

async function loadStructureExplicitly(viewer, data, format, dataLabel = 'protein') {
    const _data = await viewer.plugin.builders.data.rawData({ data: data, label: dataLabel });
    const trajectory = await viewer.plugin.builders.structure.parseTrajectory(_data, format);
    const model = await viewer.plugin.builders.structure.createModel(trajectory);
    const structure = await viewer.plugin.builders.structure.createStructure(model);

    const components = {
        polymer: await viewer.plugin.builders.structure.tryCreateComponentStatic(structure, 'polymer'),
        ligand: await viewer.plugin.builders.structure.tryCreateComponentStatic(structure, 'ligand'),
        water: await viewer.plugin.builders.structure.tryCreateComponentStatic(structure, 'water'),
    };

    const builder = viewer.plugin.builders.structure.representation;
    const update = viewer.plugin.build();
    if (components.polymer) {
        builder.buildRepresentation(update, components.polymer, {
            type: 'cartoon',
            typeParams: {
                alpha: 1,
                quality: 'high'
            }
        }, { tag: 'polymer-cartoon' });

        builder.buildRepresentation(update, components.polymer, {
            type: 'gaussian-surface',
            typeParams: {
                alpha: 0,
                quality: 'high',
                smoothness: 1
            },
            colorTheme: { name: 'hydrophobicity' }
        }, { tag: 'polymer-surface' });
    }
    if (components.ligand) builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick' }, { tag: 'ligand' });
    if (components.water) builder.buildRepresentation(update, components.water, { type: 'ball-and-stick', typeParams: { alpha: 0.6 } }, { tag: 'water' });
    await update.commit();
}

...
var structureFormat = 'pdb'.trim();
var pocketFormat = 'xyz'.trim();
var ligandFormat = 'mol2'.trim();

...

        </script>
    </body>
</html>
dsehnal commented 1 month ago

Have you seen the docking viewer example app?

smbatyankh commented 1 month ago

Yes, I attempted to use DockingViewer, but got 'undefined', which seems to indicate that the code is not accessible via the URL: https://cdn.jsdelivr.net/npm/molstar@latest/build/viewer/molstar.js

smbatyankh commented 1 month ago

I came across this response and am curious whether the implementation is still being planned or if it has already been completed: https://github.com/molstar/molstar/issues/185#issuecomment-841206018

dsehnal commented 1 month ago

I am sorry, what you are after currently isn't possible via a JavaScript snippet in an HTML document. You will need to use a bundler (e.g. Vite).

smbatyankh commented 1 month ago

Thank you for your answer. I'll consider moving forward in that direction. Additionally, I have a quick question: can I enable basic animations, such as a spinning effect, using just this JavaScript snippet?

dsehnal commented 1 month ago

This should work:

plugin.canvas3d.setProps({
  trackball: { animate: { name: 'spin', params: { speed: 1 } } } // or { name: 'off', params: { }}
});