Skip to content
Snippets Groups Projects
Select Git revision
  • f2557fe80a0afd64fae30d8426ea34c8e356713d
  • master default protected
  • rednatco-v2
  • base-pairs-ladder
  • rednatco
  • test
  • ntc-tube-uniform-color
  • ntc-tube-missing-atoms
  • restore-vertex-array-per-program
  • watlas2
  • dnatco_new
  • cleanup-old-nodejs
  • webmmb
  • fix_auth_seq_id
  • update_deps
  • ext_dev
  • ntc_balls
  • nci-2
  • plugin
  • bugfix-0.4.5
  • nci
  • v0.5.0-dev.1
  • v0.4.5
  • v0.4.4
  • v0.4.3
  • v0.4.2
  • v0.4.1
  • v0.4.0
  • v0.3.12
  • v0.3.11
  • v0.3.10
  • v0.3.9
  • v0.3.8
  • v0.3.7
  • v0.3.6
  • v0.3.5
  • v0.3.4
  • v0.3.3
  • v0.3.2
  • v0.3.1
  • v0.3.0
41 results

render-structure.ts

Blame
  • user avatar
    JonStargaryen authored
    f2557fe8
    History
    render-structure.ts 9.62 KiB
    /**
     * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
     *
     * @author Alexander Rose <alexander.rose@weirdbyte.de>
     */
    
    import './index.html';
    import { Canvas3D } from '../../mol-canvas3d/canvas3d';
    import { CIF, CifFrame } from '../../mol-io/reader/cif';
    import { Model, Structure } from '../../mol-model/structure';
    import { ColorTheme } from '../../mol-theme/color';
    import { SizeTheme } from '../../mol-theme/size';
    import { CartoonRepresentationProvider } from '../../mol-repr/structure/representation/cartoon';
    import { trajectoryFromMmCIF } from '../../mol-model-formats/structure/mmcif';
    import { MolecularSurfaceRepresentationProvider } from '../../mol-repr/structure/representation/molecular-surface';
    import { BallAndStickRepresentationProvider } from '../../mol-repr/structure/representation/ball-and-stick';
    import { GaussianSurfaceRepresentationProvider } from '../../mol-repr/structure/representation/gaussian-surface';
    import { resizeCanvas } from '../../mol-canvas3d/util';
    import { Representation } from '../../mol-repr/representation';
    import { throttleTime } from 'rxjs/operators';
    import { MarkerAction } from '../../mol-util/marker-action';
    import { EveryLoci } from '../../mol-model/loci';
    import { lociLabel } from '../../mol-theme/label';
    import { InteractionsRepresentationProvider } from '../../mol-model-props/computed/representations/interactions';
    import { InteractionsProvider } from '../../mol-model-props/computed/interactions';
    import { SecondaryStructureProvider } from '../../mol-model-props/computed/secondary-structure';
    import { SyncRuntimeContext } from '../../mol-task/execution/synchronous';
    import { AssetManager } from '../../mol-util/assets';
    import { MembraneOrientationProvider } from '../../mol-model-props/computed/membrane-orientation';
    import { SpheresBuilder } from '../../mol-geo/geometry/spheres/spheres-builder';
    import { Spheres } from '../../mol-geo/geometry/spheres/spheres';
    import { Color } from '../../mol-util/color';
    import { createRenderObject } from '../../mol-gl/render-object';
    import { MembraneOrientation } from '../../mol-model-props/computed/membrane-orientation/ANVIL';
    
    const parent = document.getElementById('app')!;
    parent.style.width = '100%';
    parent.style.height = '100%';
    
    const canvas = document.createElement('canvas');
    parent.appendChild(canvas);
    resizeCanvas(canvas, parent);
    
    const canvas3d = Canvas3D.fromCanvas(canvas);
    canvas3d.animate();
    
    const info = document.createElement('div');
    info.style.position = 'absolute';
    info.style.fontFamily = 'sans-serif';
    info.style.fontSize = '16pt';
    info.style.bottom = '20px';
    info.style.right = '20px';
    info.style.color = 'white';
    parent.appendChild(info);
    
    let prevReprLoci = Representation.Loci.Empty;
    canvas3d.input.move.pipe(throttleTime(100)).subscribe(({x, y}) => {
        const pickingId = canvas3d.identify(x, y);
        let label = '';
        if (pickingId) {
            const reprLoci = canvas3d.getLoci(pickingId);
            label = lociLabel(reprLoci.loci);
            if (!Representation.Loci.areEqual(prevReprLoci, reprLoci)) {
                canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight);
                canvas3d.mark(reprLoci, MarkerAction.Highlight);
                prevReprLoci = reprLoci;
            }
        } else {
            canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight);
            prevReprLoci = Representation.Loci.Empty;
        }
        info.innerHTML = label;
    });
    
    async function parseCif(data: string|Uint8Array) {
        const comp = CIF.parse(data);
        const parsed = await comp.run();
        if (parsed.isError) throw parsed;
        return parsed.result;
    }
    
    async function downloadCif(url: string, isBinary: boolean) {
        const data = await fetch(url);
        return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
    }
    
    async function downloadFromPdb(pdb: string) {
        const parsed = await downloadCif(`https://models.rcsb.org/${pdb}.bcif`, true);
        return parsed.blocks[0];
    }
    
    async function getModels(frame: CifFrame) {
        return await trajectoryFromMmCIF(frame).run();
    }
    
    async function getStructure(model: Model) {
        return Structure.ofModel(model);
    }
    
    const reprCtx = {
        webgl: canvas3d.webgl,
        colorThemeRegistry: ColorTheme.createRegistry(),
        sizeThemeRegistry: SizeTheme.createRegistry()
    };
    function getCartoonRepr() {
        return CartoonRepresentationProvider.factory(reprCtx, CartoonRepresentationProvider.getParams);
    }
    
    function getInteractionRepr() {
        return InteractionsRepresentationProvider.factory(reprCtx, InteractionsRepresentationProvider.getParams);
    }
    
    function getBallAndStickRepr() {
        return BallAndStickRepresentationProvider.factory(reprCtx, BallAndStickRepresentationProvider.getParams);
    }
    
    function getMolecularSurfaceRepr() {
        return MolecularSurfaceRepresentationProvider.factory(reprCtx, MolecularSurfaceRepresentationProvider.getParams);
    }
    
    function getGaussianSurfaceRepr() {
        return GaussianSurfaceRepresentationProvider.factory(reprCtx, GaussianSurfaceRepresentationProvider.getParams);
    }
    
    function getMembraneRepr(membrane: MembraneOrientation) {
        // TODO is a representation provider the right place for this?
        const spheresBuilder = SpheresBuilder.create(membrane.length, 1);
        for (let i = 0, il = membrane.length; i < il; i++) {
            spheresBuilder.add(membrane[i][0], membrane[i][1], membrane[i][2], 0);
        }
        const spheres = spheresBuilder.getSpheres();
    
        const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xCCCCCC), 1);
        const state = Spheres.Utils.createRenderableState({});
        const renderObject = createRenderObject('spheres', values, state, -1);
        console.log(renderObject);
        const repr = Representation.fromRenderObject('spheres', renderObject);
        return repr;
    }
    
    async function init() {
        const ctx = { runtime: SyncRuntimeContext, assetManager: new AssetManager() };
    
        const cif = await downloadFromPdb('3pqr');
        const models = await getModels(cif);
        const structure = await getStructure(models[0]);
    
        console.time('compute SecondaryStructure');
        await SecondaryStructureProvider.attach(ctx, structure);
        console.timeEnd('compute SecondaryStructure');
    
        console.time('compute Membrane');
        await MembraneOrientationProvider.attach(ctx, structure);
        console.timeEnd('compute Membrane');
    
        console.time('compute Interactions');
        await InteractionsProvider.attach(ctx, structure);
        console.timeEnd('compute Interactions');
        console.log(InteractionsProvider.get(structure).value);
    
        const show = {
            cartoon: true,
            interaction: true,
            ballAndStick: true,
            molecularSurface: false,
            gaussianSurface: false,
            membrane: true
        };
    
        const cartoonRepr = getCartoonRepr();
        const interactionRepr = getInteractionRepr();
        const ballAndStickRepr = getBallAndStickRepr();
        const molecularSurfaceRepr = getMolecularSurfaceRepr();
        const gaussianSurfaceRepr = getGaussianSurfaceRepr();
        const membraneRepr = getMembraneRepr(MembraneOrientationProvider.get(structure).value!);
    
        if (show.cartoon) {
            cartoonRepr.setTheme({
                color: reprCtx.colorThemeRegistry.create('element-symbol', { structure }),
                size: reprCtx.sizeThemeRegistry.create('uniform', { structure })
            });
            await cartoonRepr.createOrUpdate({ ...CartoonRepresentationProvider.defaultValues, quality: 'auto' }, structure).run();
        }
    
        if (show.interaction) {
            interactionRepr.setTheme({
                color: reprCtx.colorThemeRegistry.create('interaction-type', { structure }),
                size: reprCtx.sizeThemeRegistry.create('uniform', { structure })
            });
            await interactionRepr.createOrUpdate({ ...InteractionsRepresentationProvider.defaultValues, quality: 'auto' }, structure).run();
        }
    
        if (show.ballAndStick) {
            ballAndStickRepr.setTheme({
                color: reprCtx.colorThemeRegistry.create('element-symbol', { structure }),
                size: reprCtx.sizeThemeRegistry.create('uniform', { structure }, { value: 1 })
            });
            await ballAndStickRepr.createOrUpdate({ ...BallAndStickRepresentationProvider.defaultValues, quality: 'auto' }, structure).run();
        }
    
        if (show.molecularSurface) {
            molecularSurfaceRepr.setTheme({
                color: reprCtx.colorThemeRegistry.create('secondary-structure', { structure }),
                size: reprCtx.sizeThemeRegistry.create('physical', { structure })
            });
            console.time('molecular surface');
            await molecularSurfaceRepr.createOrUpdate({ ...MolecularSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 0.5, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run();
            console.timeEnd('molecular surface');
        }
    
        if (show.gaussianSurface) {
            gaussianSurfaceRepr.setTheme({
                color: reprCtx.colorThemeRegistry.create('secondary-structure', { structure }),
                size: reprCtx.sizeThemeRegistry.create('physical', { structure })
            });
            console.time('gaussian surface');
            await gaussianSurfaceRepr.createOrUpdate({ ...GaussianSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 1.0, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run();
            console.timeEnd('gaussian surface');
        }
    
        if (show.cartoon) canvas3d.add(cartoonRepr);
        if (show.interaction) canvas3d.add(interactionRepr);
        if (show.ballAndStick) canvas3d.add(ballAndStickRepr);
        if (show.molecularSurface) canvas3d.add(molecularSurfaceRepr);
        if (show.gaussianSurface) canvas3d.add(gaussianSurfaceRepr);
        if (show.membrane) canvas3d.add(membraneRepr);
        canvas3d.requestCameraReset();
        // canvas3d.setProps({ trackball: { ...canvas3d.props.trackball, spin: true } })
    }
    
    init();