molstar / molstar

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

Show residues as spacefill #1125

Open nataliarosa9 opened 2 weeks ago

nataliarosa9 commented 2 weeks ago

How can I show specific residues, such as space fill, size theme uniform, and colour theme cartoons, after selection?

  import React, { useEffect, useRef, useMemo } from 'react';
  import { createPluginUI } from 'molstar/lib/mol-plugin-ui';
  import { ColorNames } from 'molstar/lib/mol-util/color/names';
  import 'molstar/lib/mol-plugin-ui/skin/light.scss';
  import { renderReact18 } from 'molstar/lib/mol-plugin-ui/react18';
  import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
  import { Script } from 'molstar/lib/mol-script/script';
  import { StructureSelection } from 'molstar/lib/mol-model/structure/query';
  import { Expression } from 'molstar/lib/mol-script/language/expression';
  import { MolScriptBuilder as MS, MolScriptBuilder } from 'molstar/lib/mol-script/language/builder';

  const MolstarViewer = ({ pdbId }) => {

  const viewerRef = useRef(null);
  const pluginInstanceRef = useRef(null);

  const initMolstar = useMemo(() => async () => {
          if (viewerRef.current && !pluginInstanceRef.current) {
            const plugin = await createPluginUI({
              target: viewerRef.current,
              layoutIsExpanded: false,
              layoutShowControls: false,
              layoutShowRemoteState: false,
              layoutShowSequence: true,
              layoutShowLog: false,
              layoutShowLeftPanel: false,
              viewportShowExpand: false,
              viewportShowSelectionMode: false,
              viewportShowAnimation: false,
              pdbProvider: 'rcsb',
              backgroundColor: 'white',
              render: renderReact18,
            });
      pluginInstanceRef.current = plugin;

      try {
        const data = await pluginInstanceRef.current.builders.data.download(
          { url: `https://files.rcsb.org/download/${pdbId}.cif` },
          { state: { isGhost: false } }
        );
        const trajectory = await pluginInstanceRef.current.builders.structure.parseTrajectory(data, 'mmcif');
        const structure = await pluginInstanceRef.current.builders.structure.hierarchy.applyPreset(
          trajectory,
          'default'
        );

      // Change background color
      const renderer = plugin.canvas3d.props.renderer;
      PluginCommands.Canvas3D.SetSettings(plugin, { settings: { renderer: { ...renderer, backgroundColor: ColorNames.white} } });

  const dta = plugin.managers.structure.hierarchy.current.structures[0]?.cell.obj?.data;
    if (!dta) return;

    const selection = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
        "chain-test": Q.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(),'A']),
        "residue-test": Q.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.label_seq_id(), 4]),
    }), dta);
    const loci = StructureSelection.toLociWithSourceUnits(selection);
    plugin.managers.interactivity.lociSelects.select({ loci });

  } catch (error) {
    console.error('Failed to load the PDB structure:', error);
  }
}
  }, [pdbId]);

  useEffect(() => {
    initMolstar();

    return () => {
      if (pluginInstanceRef.current) {
        pluginInstanceRef.current.dispose();
        pluginInstanceRef.current = null;
      }
    };
  }, [initMolstar]);

  return <div key={pdbId} ref={viewerRef} style={{ width: '100%', height: '100%' }} />;
};

export default MolstarViewer;

1TQN

dsehnal commented 1 week ago

Hi @nataliarosa9,

The proteopedia-wrapper het groups example does something very similar


When you are pasting in code for your current solution, could you please format it properly next time (see for example this)?

nataliarosa9 commented 4 days ago

Hi! I attempted to implement the code based on the provided example. So far, I have only gotten it to work on a whole structure. I aim to select a few atoms and apply their new representation.

Do you have any ideas on how I can fix it?

import React, { useEffect, useRef, useMemo } from 'react';
import { createPluginUI } from 'molstar/lib/mol-plugin-ui';
import { ColorNames } from 'molstar/lib/mol-util/color/names';
import 'molstar/lib/mol-plugin-ui/skin/light.scss';
import { renderReact18 } from 'molstar/lib/mol-plugin-ui/react18';
import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
import { Script } from 'molstar/lib/mol-script/script';
import { StructureSelection } from 'molstar/lib/mol-model/structure/query';
import { MolScriptBuilder as MS, MolScriptBuilder } from 'molstar/lib/mol-script/language/builder';
import { StateTransforms } from 'molstar/lib/mol-plugin-state/transforms';
import { createStructureRepresentationParams } from 'molstar/lib/mol-plugin-state/helpers/structure-representation-params';

const MolstarViewer = ({ pdbId }) => {
  const viewerRef = useRef(null);
  const pluginInstanceRef = useRef(null);

const initMolstar = useMemo(() => async () => {
  if (viewerRef.current && !pluginInstanceRef.current) {
    const plugin = await createPluginUI({
      target: viewerRef.current,
      layoutIsExpanded: false,
      layoutShowControls: false,
      layoutShowRemoteState: false,
      layoutShowSequence: true,
      layoutShowLog: false,
      layoutShowLeftPanel: false,
      viewportShowExpand: false,
      viewportShowSelectionMode: false,
      viewportShowAnimation: false,
      pdbProvider: 'rcsb',
      backgroundColor: 'white',
      render: renderReact18,
    });
    pluginInstanceRef.current = plugin;

    try {
      const data = await pluginInstanceRef.current.builders.data.download(
        { url: `https://files.rcsb.org/download/${pdbId}.cif` },
        { state: { isGhost: false } }
      );
      const trajectory = await pluginInstanceRef.current.builders.structure.parseTrajectory(data, 'mmcif');
      const structure = await pluginInstanceRef.current.builders.structure.hierarchy.applyPreset(
        trajectory,
        'default'
      );

      // Change background color
      const renderer = plugin.canvas3d.props.renderer;
      PluginCommands.Canvas3D.SetSettings(plugin, { settings: { renderer: { ...renderer, backgroundColor: ColorNames.white } } });

      const dta = plugin.managers.structure.hierarchy.current.structures[0]?.cell.obj?.data;
      if (!dta) return;

      const selection = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
        "chain-test": Q.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), 'A']),
        "residue-test": Q.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.label_seq_id(), 4]),
      }), dta);

      const loci = StructureSelection.toLociWithSourceUnits(selection);

      const cartoon = structure.representation.representations.polymer;

      // Create and apply custom representation
      const reprParams = createStructureRepresentationParams(plugin, undefined, {
        type: 'spacefill',
        color: 'uniform',
        colorParams: { value: ColorNames.red },
        size: 'uniform',
        sizeParams: { value: 1 }
      });

      const update = await plugin
      .build()
      .to(cartoon)
      .update(reprParams);

      await update.commit();

    } catch (error) {
      console.error('Failed to load the PDB structure:', error);
    }
  }
}, [pdbId]);

useEffect(() => {
  initMolstar();

  return () => {
    if (pluginInstanceRef.current) {
      pluginInstanceRef.current.dispose();
      pluginInstanceRef.current = null;
    }
  };
}, [initMolstar]);

  return <div key={pdbId} ref={viewerRef} style={{ width: '100%', height: '100%' }} />;
};

export default MolstarViewer;

immagine

nataliarosa9 commented 1 day ago

Hi! I managed to display some residues as spacefill representations. I want to overpaint the residues in selectionPositions, but I get this error:

Failed to load the PDB structure: TypeError: components is not iterable eachRepr structure-overpaint.js:48 setStructureOverpaint structure-overpaint.js:10 initMolstar MolstarViewer.jsx:110 MolstarViewer MolstarViewer.jsx:120

Do you have any ideas on how I can solve it?

immagine

import React, { useEffect, useRef, useMemo } from 'react';
import { createPluginUI } from 'molstar/lib/mol-plugin-ui';
import { ColorNames } from 'molstar/lib/mol-util/color/names';
import 'molstar/lib/mol-plugin-ui/skin/light.scss';
import { renderReact18 } from 'molstar/lib/mol-plugin-ui/react18';
import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
import { Script } from 'molstar/lib/mol-script/script';
import { StructureSelection } from 'molstar/lib/mol-model/structure/query';
import { MolScriptBuilder as MS, MolScriptBuilder } from 'molstar/lib/mol-script/language/builder';
import { StateTransforms } from 'molstar/lib/mol-plugin-state/transforms';
import { createStructureRepresentationParams } from 'molstar/lib/mol-plugin-state/helpers/structure-representation-params';
import { Color } from "molstar/lib/mol-util/color";
import { setStructureOverpaint } from 'molstar/lib/mol-plugin-state/helpers/structure-overpaint'

const MolstarViewer = ({ pdbId }) => {
  const viewerRef = useRef(null);
  const pluginInstanceRef = useRef(null);

  const initMolstar = useMemo(() => async () => {
    if (viewerRef.current && !pluginInstanceRef.current) {
      const plugin = await createPluginUI({
        target: viewerRef.current,
        layoutIsExpanded: false,
        layoutShowControls: false,
        layoutShowRemoteState: false,
        layoutShowSequence: true,
        layoutShowLog: false,
        layoutShowLeftPanel: false,
        viewportShowExpand: false,
        viewportShowSelectionMode: false,
        viewportShowAnimation: false,
        pdbProvider: 'rcsb',
        backgroundColor: 'white',
        render: renderReact18,
      });
      pluginInstanceRef.current = plugin;

      try {
        const data = await pluginInstanceRef.current.builders.data.download(
          { url: `https://files.rcsb.org/download/${pdbId}.cif` },
          { state: { isGhost: true } }
        );
        const trajectory = await pluginInstanceRef.current.builders.structure.parseTrajectory(data, 'mmcif');
        const structure = await pluginInstanceRef.current.builders.structure.hierarchy.applyPreset(
          trajectory,
          'default'
          , {
            showUnitcell: false,
            representationPreset: 'auto',
        }
        );

        // Change background color
        const renderer = plugin.canvas3d.props.renderer;
        PluginCommands.Canvas3D.SetSettings(plugin, { settings: { renderer: { ...renderer, backgroundColor: ColorNames.white } } });

        const dta = plugin.managers.structure.hierarchy.current.structures[0]?.cell.obj?.data;
        if (!dta) return;

        // Select multiples residues in the sequence
        const selection = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
        "chain-test": Q.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), 'A']),
        'residue-test': Q.core.set.has([Q.set(1,3,6), Q.ammp('auth_seq_id')]),
        'group-by': Q.struct.atomProperty.macromolecular.residueKey(),}), dta);

        //const loci = StructureSelection.toLociWithSourceUnits(selection);
        //plugin.managers.interactivity.lociSelects.select({ loci });

        // Get polymer representation
        const cartoon = structure.representation.representations.polymer;

        // Create and apply custom representation
        const reprParamsStructureResetColor = createStructureRepresentationParams(plugin, undefined, {
          type: 'cartoon',
          color: 'uniform',
          colorParams: { value: ColorNames.gray }
        });

        // Create and apply custom representation - Show residue as spacefill (Displays atomic/coarse elements as spheres)
        const reprParams = createStructureRepresentationParams(plugin, undefined, {
          type: 'spacefill',
          color: 'uniform',
          colorParams: { value: Color(0xf0e68c) },
          size: 'uniform',
          sizeParams: { value: 2 }
        });

        const update = await plugin
        .build()
        .to(cartoon)
        .update(reprParamsStructureResetColor);

        const update2 = await plugin
        .build()
        .to(cartoon)
         .apply(StateTransforms.Model.StructureSelectionFromExpression, { label: 'Surroundings', expression: selection })
         .apply(StateTransforms.Representation.StructureRepresentation3D, reprParams);

        await update.commit();
        await update2.commit();

        // Select residue position
        const selectionPositions = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
        "chain-test": Q.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), 'A']),
        'residue-test': Q.core.set.has([Q.set(2,4,7), Q.ammp('auth_seq_id')]),
        'group-by': Q.struct.atomProperty.macromolecular.residueKey(),}), dta);

        const loci = StructureSelection.toLociWithSourceUnits(selectionPositions);
        await setStructureOverpaint(plugin, dta, Color(0xf0e68c), loci);

      } catch (error) {
        console.error('Failed to load the PDB structure:', error);
      }
        }
      }, [pdbId]);

  useEffect(() => {
    initMolstar();

    return () => {
      if (pluginInstanceRef.current) {
        pluginInstanceRef.current.dispose();
        pluginInstanceRef.current = null;
      }
    };
  }, [initMolstar]);

  return <div key={pdbId} ref={viewerRef} style={{ width: '100%', height: '100%' }} />;
};

export default MolstarViewer;