Forráskód Böngészése

removed superseded label transfroms and representations

Alexander Rose 5 éve
szülő
commit
f2c5cd978b

+ 1 - 3
src/mol-plugin/behavior.ts

@@ -14,7 +14,6 @@ import * as StaticMisc from './behavior/static/misc'
 import * as DynamicRepresentation from './behavior/dynamic/representation'
 import * as DynamicRepresentation from './behavior/dynamic/representation'
 import * as DynamicCamera from './behavior/dynamic/camera'
 import * as DynamicCamera from './behavior/dynamic/camera'
 import * as DynamicCustomProps from './behavior/dynamic/custom-props'
 import * as DynamicCustomProps from './behavior/dynamic/custom-props'
-import * as DynamicLabels from './behavior/dynamic/labels'
 
 
 export const BuiltInPluginBehaviors = {
 export const BuiltInPluginBehaviors = {
     State: StaticState,
     State: StaticState,
@@ -26,6 +25,5 @@ export const BuiltInPluginBehaviors = {
 export const PluginBehaviors = {
 export const PluginBehaviors = {
     Representation: DynamicRepresentation,
     Representation: DynamicRepresentation,
     Camera: DynamicCamera,
     Camera: DynamicCamera,
-    CustomProps: DynamicCustomProps,
-    Labels: DynamicLabels
+    CustomProps: DynamicCustomProps
 }
 }

+ 0 - 233
src/mol-plugin/behavior/dynamic/labels.ts

@@ -1,233 +0,0 @@
-/**
- * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { PluginContext } from '../../../mol-plugin/context';
-import { PluginBehavior } from '../behavior';
-import { ParamDefinition as PD } from '../../../mol-util/param-definition'
-import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
-import { PluginStateObject as SO, PluginStateObject } from '../../state/objects';
-import { StateObjectCell, State, StateSelection } from '../../../mol-state';
-import { RuntimeContext } from '../../../mol-task';
-import { Shape } from '../../../mol-model/shape';
-import { Text } from '../../../mol-geo/geometry/text/text';
-import { ShapeRepresentation } from '../../../mol-repr/shape/representation';
-import { ColorNames } from '../../../mol-util/color/names';
-import { TextBuilder } from '../../../mol-geo/geometry/text/text-builder';
-import { Unit, StructureElement, StructureProperties } from '../../../mol-model/structure';
-import { SetUtils } from '../../../mol-util/set';
-import { arrayEqual } from '../../../mol-util';
-import { MoleculeType } from '../../../mol-model/structure/model/types';
-import { getElementMoleculeType } from '../../../mol-model/structure/util';
-
-// TODO
-// - support more object types than structures
-// - tether label to the element nearest to the bounding sphere center
-// - [Started] multiple levels of labels: structure, polymer, ligand
-// - show structure/unit label only when there is a representation with sufficient overlap
-// - support highlighting
-// - better support saccharides (use data available after re-mediation)
-// - size based on min bbox dimension (to avoid huge labels for very long but narrow polymers)
-// - fixed size labels (invariant to zoom) [needs feature in text geo]
-// - ??? max label length
-// - ??? multi line labels [needs feature in text geo]
-// - ??? use prevalent (how to define) color of representations of a structure to color the label
-// - completely different approach (render not as 3d objects): overlay free layout in screenspace with occlusion info from bboxes
-
-export type SceneLabelsLevels = 'structure' | 'polymer' | 'ligand'
-
-export const SceneLabelsParams = {
-    ...Text.Params,
-
-    background: PD.Boolean(true),
-    backgroundMargin: PD.Numeric(0.2, { min: 0, max: 1, step: 0.01 }),
-    backgroundColor: PD.Color(ColorNames.snow),
-    backgroundOpacity: PD.Numeric(0.9, { min: 0, max: 1, step: 0.01 }),
-
-    levels: PD.MultiSelect([] as SceneLabelsLevels[], [
-        ['structure', 'structure'], ['polymer', 'polymer'], ['ligand', 'ligand']
-    ] as [SceneLabelsLevels, string][]),
-}
-export type SceneLabelsParams = typeof SceneLabelsParams
-export type SceneLabelsProps = PD.Values<typeof SceneLabelsParams>
-
-interface LabelsData {
-    transforms: Mat4[]
-    texts: string[]
-    positions: Vec3[]
-    sizes: number[]
-    depths: number[]
-}
-
-function getLabelsText(data: LabelsData, props: PD.Values<Text.Params>, text?: Text) {
-    const { texts, positions, depths } = data
-    const textBuilder = TextBuilder.create(props, texts.length * 10, texts.length * 10 / 2, text)
-    for (let i = 0, il = texts.length; i < il; ++i) {
-        const p = positions[i]
-        textBuilder.add(texts[i], p[0], p[1], p[2], depths[i], 1, i)
-    }
-    return textBuilder.getText()
-}
-
-export const SceneLabels = PluginBehavior.create<SceneLabelsProps>({
-    name: 'scene-labels',
-    category: 'representation',
-    display: { name: 'Scene Labels' },
-    canAutoUpdate: () => true,
-    ctor: class extends PluginBehavior.Handler<SceneLabelsProps> {
-        private data: LabelsData = {
-            transforms: [Mat4.identity()],
-            texts: [],
-            positions: [],
-            sizes: [],
-            depths: []
-        }
-        private repr: ShapeRepresentation<LabelsData, Text, SceneLabelsParams>
-        private geo = Text.createEmpty()
-        private structures = new Set<SO.Molecule.Structure>()
-
-        constructor(protected ctx: PluginContext, protected params: SceneLabelsProps) {
-            super(ctx, params)
-            this.repr = ShapeRepresentation(this.getLabelsShape, Text.Utils)
-            ctx.events.state.object.created.subscribe(this.triggerUpdate)
-            ctx.events.state.object.removed.subscribe(this.triggerUpdate)
-            ctx.events.state.object.updated.subscribe(this.triggerUpdate)
-            ctx.events.state.cell.stateUpdated.subscribe(this.triggerUpdate)
-        }
-
-        private triggerUpdate = async () => {
-            await this.update(this.params)
-        }
-
-        private getColor = () => ColorNames.dimgrey
-        private getSize = (groupId: number) => this.data.sizes[groupId]
-        private getLabel = () => ''
-
-        private getLabelsShape = (ctx: RuntimeContext, data: LabelsData, props: SceneLabelsProps, shape?: Shape<Text>) => {
-            this.geo = getLabelsText(data, props, this.geo)
-            return Shape.create('Scene Labels', data, this.geo, this.getColor, this.getSize, this.getLabel, data.transforms)
-        }
-
-        /** Update structures to be labeled, returns true if changed */
-        private updateStructures(p: SceneLabelsProps) {
-            const state = this.ctx.state.dataState
-            const structures = state.selectQ(q => q.rootsOfType(PluginStateObject.Molecule.Structure));
-            const rootStructures = new Set<SO.Molecule.Structure>()
-            for (const s of structures) {
-                const rootStructure = getRootStructure(s, state)
-                if (!rootStructure || !SO.Molecule.Structure.is(rootStructure.obj)) continue
-                if (!s.state.isHidden) {
-                    rootStructures.add(rootStructure.obj)
-                }
-            }
-            if (!SetUtils.areEqual(rootStructures, this.structures)) {
-                this.structures = rootStructures
-                return true
-            } else {
-                return false
-            }
-        }
-
-        private updateLabels(p: SceneLabelsProps) {
-            const l = StructureElement.Location.create()
-
-            const { texts, positions, sizes, depths } = this.data
-            texts.length = 0
-            positions.length = 0
-            sizes.length = 0
-            depths.length = 0
-
-            this.structures.forEach(structure => {
-                if (p.levels.includes('structure')) {
-                    texts.push(`${structure.data.model.label}`)
-                    positions.push(structure.data.boundary.sphere.center)
-                    sizes.push(structure.data.boundary.sphere.radius / 10)
-                    depths.push(structure.data.boundary.sphere.radius)
-                }
-
-                for (let i = 0, il = structure.data.units.length; i < il; ++i) {
-                    let label = ''
-                    const u = structure.data.units[i]
-                    l.unit = u
-                    l.element = u.elements[0]
-
-                    if (p.levels.includes('polymer') && u.polymerElements.length) {
-                        label = `${StructureProperties.entity.pdbx_description(l).join(', ')} (${getAsymId(u)(l)})`
-                    }
-
-                    if (p.levels.includes('ligand') && !u.polymerElements.length) {
-                        const moleculeType = getElementMoleculeType(u, u.elements[0])
-                        if (moleculeType === MoleculeType.Other || moleculeType === MoleculeType.Saccharide) {
-                            label = `${StructureProperties.entity.pdbx_description(l).join(', ')} (${getAsymId(u)(l)})`
-                        }
-                    }
-
-                    if (label) {
-                        texts.push(label)
-                        const { center, radius } = u.lookup3d.boundary.sphere
-                        const transformedCenter = Vec3.transformMat4(Vec3.zero(), center, u.conformation.operator.matrix)
-                        positions.push(transformedCenter)
-                        sizes.push(Math.max(2, radius / 10))
-                        depths.push(radius)
-                    }
-                }
-            })
-        }
-
-        register(): void { }
-
-        async update(p: SceneLabelsProps) {
-            // console.log('update')
-            let updated = false
-            if (this.updateStructures(p) || !arrayEqual(this.params.levels, p.levels)) {
-                // console.log('update with data')
-                this.updateLabels(p)
-                await this.repr.createOrUpdate(p, this.data).run()
-                updated = true
-            } else if (!PD.areEqual(SceneLabelsParams, this.params, p)) {
-                // console.log('update props only')
-                await this.repr.createOrUpdate(p).run()
-                updated = true
-            }
-            if (updated) {
-                Object.assign(this.params, p)
-                this.ctx.canvas3d?.add(this.repr)
-            }
-            return updated;
-        }
-
-        unregister() {
-
-        }
-    },
-    params: () => SceneLabelsParams
-});
-
-//
-
-function getRootStructure(root: StateObjectCell, state: State) {
-    let parent: StateObjectCell | undefined
-    while (true) {
-        const _parent = StateSelection.findAncestorOfType(state.tree, state.cells, root.transform.ref, [PluginStateObject.Molecule.Structure])
-        if (_parent) {
-            parent = _parent
-            root = _parent
-        } else {
-            break
-        }
-    }
-    return parent ? parent :
-        SO.Molecule.Structure.is(root.obj) ? root : undefined
-}
-
-function getAsymId(unit: Unit): StructureElement.Property<string> {
-    switch (unit.kind) {
-        case Unit.Kind.Atomic:
-            return StructureProperties.chain.auth_asym_id
-        case Unit.Kind.Spheres:
-        case Unit.Kind.Gaussians:
-            return StructureProperties.coarse.asym_id
-    }
-}

+ 0 - 1
src/mol-plugin/index.ts

@@ -47,7 +47,6 @@ export const DefaultPluginSpec: PluginSpec = {
         PluginSpec.Action(StateTransforms.Model.ModelFromTrajectory),
         PluginSpec.Action(StateTransforms.Model.ModelFromTrajectory),
         PluginSpec.Action(StateTransforms.Model.StructureSelectionFromScript),
         PluginSpec.Action(StateTransforms.Model.StructureSelectionFromScript),
         PluginSpec.Action(StateTransforms.Representation.StructureRepresentation3D),
         PluginSpec.Action(StateTransforms.Representation.StructureRepresentation3D),
-        PluginSpec.Action(StateTransforms.Representation.StructureLabels3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsDistance3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsDistance3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsAngle3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsAngle3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsDihedral3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsDihedral3D),

+ 0 - 6
src/mol-plugin/state/animation/built-in.ts

@@ -113,9 +113,6 @@ export const AnimateAssemblyUnwind = PluginStateAnimation.create({
         const update = state.build();
         const update = state.build();
         let changed = false;
         let changed = false;
         for (const r of reprs) {
         for (const r of reprs) {
-            // TODO: find a better way to handle this, perhaps add a different state object??
-            if (r.transform.transformer === StateTransforms.Representation.StructureLabels3D) continue;
-
             const unwinds = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D, r.transform.ref));
             const unwinds = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D, r.transform.ref));
             if (unwinds.length > 0) continue;
             if (unwinds.length > 0) continue;
 
 
@@ -183,9 +180,6 @@ export const AnimateUnitsExplode = PluginStateAnimation.create({
         const update = state.build();
         const update = state.build();
         let changed = false;
         let changed = false;
         for (const r of reprs) {
         for (const r of reprs) {
-            // TODO: find a better way to handle this, perhaps add a different state object??
-            if (r.transform.transformer === StateTransforms.Representation.StructureLabels3D) continue;
-
             const explodes = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.ExplodeStructureRepresentation3D, r.transform.ref));
             const explodes = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.ExplodeStructureRepresentation3D, r.transform.ref));
             if (explodes.length > 0) continue;
             if (explodes.length > 0) continue;
 
 

+ 0 - 49
src/mol-plugin/state/transforms/representation.ts

@@ -20,9 +20,7 @@ import { BuiltInSizeThemeName, SizeTheme } from '../../../mol-theme/size';
 import { createTheme, ThemeRegistryContext } from '../../../mol-theme/theme';
 import { createTheme, ThemeRegistryContext } from '../../../mol-theme/theme';
 import { ParamDefinition as PD } from '../../../mol-util/param-definition';
 import { ParamDefinition as PD } from '../../../mol-util/param-definition';
 import { PluginStateObject as SO, PluginStateTransform } from '../objects';
 import { PluginStateObject as SO, PluginStateTransform } from '../objects';
-import { Text } from '../../../mol-geo/geometry/text/text';
 import { ColorNames } from '../../../mol-util/color/names';
 import { ColorNames } from '../../../mol-util/color/names';
-import { getLabelRepresentation } from '../../../mol-plugin/util/structure-labels';
 import { ShapeRepresentation } from '../../../mol-repr/shape/representation';
 import { ShapeRepresentation } from '../../../mol-repr/shape/representation';
 import { StructureUnitTransforms } from '../../../mol-model/structure/structure/util/unit-transforms';
 import { StructureUnitTransforms } from '../../../mol-model/structure/structure/util/unit-transforms';
 import { unwindStructureAssembly, explodeStructure } from '../animation/helpers';
 import { unwindStructureAssembly, explodeStructure } from '../animation/helpers';
@@ -41,7 +39,6 @@ import { DihedralParams, DihedralRepresentation } from '../../../mol-repr/shape/
 
 
 export { StructureRepresentation3D }
 export { StructureRepresentation3D }
 export { StructureRepresentation3DHelpers }
 export { StructureRepresentation3DHelpers }
-export { StructureLabels3D}
 export { ExplodeStructureRepresentation3D }
 export { ExplodeStructureRepresentation3D }
 export { UnwindStructureAssemblyRepresentation3D }
 export { UnwindStructureAssemblyRepresentation3D }
 export { OverpaintStructureRepresentation3DFromScript }
 export { OverpaintStructureRepresentation3DFromScript }
@@ -241,52 +238,6 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({
     }
     }
 });
 });
 
 
-type StructureLabels3D = typeof StructureLabels3D
-const StructureLabels3D = PluginStateTransform.BuiltIn({
-    name: 'structure-labels-3d',
-    display: '3D Labels',
-    from: SO.Molecule.Structure,
-    to: SO.Molecule.Structure.Representation3D,
-    params: {
-        // TODO: other targets
-        target: PD.MappedStatic('residues', {
-            'elements': PD.Group({ }),
-            'residues': PD.Group({ }),
-            'static-text': PD.Group({
-                value: PD.Text(''),
-                size: PD.Optional(PD.Numeric(1, { min: 1, max: 1000, step: 0.1 })),
-                // TODO: this changes the position while rotated etc... fix
-                position: PD.Optional(Text.Params.attachment)
-            }, { isFlat: true })
-        }),
-        options: PD.Group({
-            ...Text.Params,
-
-            background: PD.Boolean(true),
-            backgroundMargin: PD.Numeric(0.2, { min: 0, max: 1, step: 0.01 }),
-            backgroundColor: PD.Color(ColorNames.snow),
-            backgroundOpacity: PD.Numeric(0.9, { min: 0, max: 1, step: 0.01 }),
-        })
-    }
-})({
-    canAutoUpdate({ oldParams, newParams }) {
-        return (oldParams.target.name === 'static-text' && newParams.target.name === 'static-text' && oldParams.target.params.value === newParams.target.params.value)
-            || newParams.target.name === oldParams.target.name;
-    },
-    apply({ a, params }) {
-        return Task.create('Structure Labels', async ctx => {
-            const repr = await getLabelRepresentation(ctx, a.data, params);
-            return new SO.Molecule.Structure.Representation3D({ repr, source: a }, { label: `Labels`, description: params.target.name });
-        });
-    },
-    update({ a, b, newParams }) {
-        return Task.create('Structure Labels', async ctx => {
-            await getLabelRepresentation(ctx, a.data, newParams, b.data.repr as ShapeRepresentation<any, any, any>);
-            return StateTransformer.UpdateResult.Updated;
-        });
-    }
-});
-
 type UnwindStructureAssemblyRepresentation3D = typeof UnwindStructureAssemblyRepresentation3D
 type UnwindStructureAssemblyRepresentation3D = typeof UnwindStructureAssemblyRepresentation3D
 const UnwindStructureAssemblyRepresentation3D = PluginStateTransform.BuiltIn({
 const UnwindStructureAssemblyRepresentation3D = PluginStateTransform.BuiltIn({
     name: 'unwind-structure-assembly-representation-3d',
     name: 'unwind-structure-assembly-representation-3d',

+ 0 - 136
src/mol-plugin/util/structure-labels.ts

@@ -1,136 +0,0 @@
-/**
- * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { Structure, StructureElement, StructureProperties, Unit } from '../../mol-model/structure';
-import { StateTransformer } from '../../mol-state';
-import { StructureLabels3D } from '../state/transforms/representation';
-import { ShapeRepresentation } from '../../mol-repr/shape/representation';
-import { Vec3 } from '../../mol-math/linear-algebra';
-import { Text } from '../../mol-geo/geometry/text/text';
-import { TextBuilder } from '../../mol-geo/geometry/text/text-builder';
-import { Shape } from '../../mol-model/shape';
-import { ColorNames } from '../../mol-util/color/names';
-import { RuntimeContext } from '../../mol-task';
-import { ParamDefinition as PD } from '../../mol-util/param-definition';
-import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
-
-interface LabelsData {
-    texts: string[],
-    positions: Vec3[],
-    sizes: number[],
-    depths: number[]
-}
-
-function getLabelsText(data: LabelsData, props: PD.Values<Text.Params>, text?: Text) {
-    const { texts, positions, depths } = data
-    const textBuilder = TextBuilder.create(props, texts.length * 10, texts.length * 10 / 2, text)
-    for (let i = 0, il = texts.length; i < il; ++i) {
-        const p = positions[i]
-        textBuilder.add(texts[i], p[0], p[1], p[2], depths[i], 1, i)
-    }
-    return textBuilder.getText()
-}
-
-export async function getLabelRepresentation(ctx: RuntimeContext, structure: Structure, params: StateTransformer.Params<StructureLabels3D>, prev?: ShapeRepresentation<LabelsData, Text, Text.Params>) {
-    const repr = prev || ShapeRepresentation(getLabelsShape, Text.Utils);
-    const data = getLabelData(structure, params);
-    await repr.createOrUpdate(params.options, data).runInContext(ctx);
-    repr.setState({ pickable: false })
-    return repr;
-}
-
-function getLabelsShape(ctx: RuntimeContext, data: LabelsData, props: PD.Values<Text.Params>, shape?: Shape<Text>) {
-    const geo = getLabelsText(data, props, shape && shape.geometry);
-    return Shape.create('Scene Labels', data, geo, () => ColorNames.dimgrey, g => data.sizes[g], () => '')
-}
-
-const boundaryHelper = new BoundaryHelper();
-function getLabelData(structure: Structure, params: StateTransformer.Params<StructureLabels3D>): LabelsData {
-    if (params.target.name === 'static-text') {
-        return getLabelDataStatic(structure, params.target.params.value, params.target.params.size || 1, params.target.params.position || 'middle-center');
-    } else {
-        return getLabelDataComputed(structure, params.target.name);
-    }
-
-}
-
-function getLabelDataStatic(structure: Structure, text: string, size: number, position: Text.Params['attachment']['defaultValue']): LabelsData {
-    const boundary = structure.boundary.sphere;
-    let oX = 0, oY = 0;
-    if (position.indexOf('left') >= 0) oX = -boundary.radius;
-    if (position.indexOf('right') >= 0) oX = boundary.radius;
-    if (position.indexOf('top') >= 0) oY = boundary.radius;
-    if (position.indexOf('bottom') >= 0) oY = -boundary.radius;
-    return {
-        texts: [text],
-        positions: [Vec3.add(Vec3.zero(), boundary.center, Vec3.create(oX, oY, 0))],
-        sizes: [size],
-        depths: [boundary.radius + Math.sqrt(oX * oX + oY * oY)]
-    };
-}
-
-function getLabelDataComputed(structure: Structure, level: 'elements' | 'residues'): LabelsData {
-    const data: LabelsData = { texts: [], positions: [], sizes: [], depths: [] };
-
-    const l = StructureElement.Location.create();
-    const { units } = structure;
-
-    const { label_atom_id } = StructureProperties.atom;
-    const { auth_seq_id, label_comp_id } = StructureProperties.residue;
-    const { auth_asym_id } = StructureProperties.chain;
-    const p = Vec3.zero();
-
-    for (const unit of units) {
-        // TODO: support coarse models
-
-        if (unit.kind !== Unit.Kind.Atomic) continue;
-        l.unit = unit;
-        const elements = unit.elements;
-
-        const pos = unit.conformation.position;
-
-        if (level === 'elements') {
-            for (let j = 0, _j = elements.length; j < _j; j++) {
-                l.element = elements[j];
-
-                pos(l.element, p);
-                data.texts.push(label_atom_id(l));
-                data.positions.push(Vec3.clone(p));
-                data.sizes.push(1);
-                data.depths.push(2);
-            }
-        } else {
-            const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index;
-
-            let i = 0, len = elements.length;
-            while (i < len) {
-                const start = i, rI = residueIndex[elements[i]];
-                i++;
-                while (i < len && residueIndex[elements[i]] === rI) i++;
-
-                boundaryHelper.reset(0);
-                for (let eI = start; eI < i; eI++) {
-                    pos(elements[eI], p);
-                    boundaryHelper.boundaryStep(p, 0);
-                }
-                boundaryHelper.finishBoundaryStep();
-                for (let eI = start; eI < i; eI++) {
-                    pos(elements[eI], p);
-                    boundaryHelper.extendStep(p, 0);
-                }
-
-                l.element = elements[start];
-
-                data.texts.push(`${label_comp_id(l)} ${auth_seq_id(l)}:${auth_asym_id(l)}`);
-                data.positions.push(Vec3.clone(boundaryHelper.center));
-                data.sizes.push(Math.max(1, boundaryHelper.radius / 5));
-                data.depths.push(boundaryHelper.radius);
-            }
-        }
-    }
-
-    return data;
-}