From 118daa2b2537ef27004a002326ef812c076a7e59 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Sat, 2 Mar 2019 14:07:56 +0100 Subject: [PATCH] StructureElement.Loci.toScriptExpression, mol-script fixes --- .../structure/query/queries/modifiers.ts | 3 +- src/mol-model/structure/structure/element.ts | 41 +++++++++++++++---- .../dynamic/volume-streaming/behavior.ts | 25 +++++------ .../language/symbol-table/structure-query.ts | 4 ++ src/mol-script/runtime/query/table.ts | 13 ++++++ 5 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/mol-model/structure/query/queries/modifiers.ts b/src/mol-model/structure/query/queries/modifiers.ts index 0b0904515..f85855d26 100644 --- a/src/mol-model/structure/query/queries/modifiers.ts +++ b/src/mol-model/structure/query/queries/modifiers.ts @@ -279,11 +279,10 @@ export function expandProperty(query: StructureQuery, property: QueryFn): Struct ctx.element.element = elements[i]; const p = property(ctx); if (!propertyToStructureIndexMap.has(p)) continue; - const indices = propertyToStructureIndexMap.get(p)!.array; for (let _sI = 0, __sI = indices.length; _sI < __sI; _sI++) { - builders[indices[i]].addToUnit(unit.id, elements[i]); + builders[indices[_sI]].addToUnit(unit.id, elements[i]); } } } diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts index 1bd19cde9..db379cf93 100644 --- a/src/mol-model/structure/structure/element.ts +++ b/src/mol-model/structure/structure/element.ts @@ -4,14 +4,17 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { OrderedSet, SortedArray } from 'mol-data/int' -import Unit from './unit' +import { UniqueArray } from 'mol-data/generic'; +import { OrderedSet, SortedArray } from 'mol-data/int'; +import { BoundaryHelper } from 'mol-math/geometry/boundary-helper'; +import { Vec3 } from 'mol-math/linear-algebra'; +import { MolScriptBuilder as MS } from 'mol-script/language/builder'; import { ElementIndex } from '../model'; -import { ResidueIndex, ChainIndex } from '../model/indexing'; +import { ChainIndex, ResidueIndex } from '../model/indexing'; import Structure from './structure'; +import Unit from './unit'; import { Boundary } from './util/boundary'; -import { BoundaryHelper } from 'mol-math/geometry/boundary-helper'; -import { Vec3 } from 'mol-math/linear-algebra'; +import { StructureProperties } from '../structure'; interface StructureElement<U = Unit> { readonly kind: 'element-location', @@ -38,11 +41,11 @@ namespace StructureElement { function _wrongUnitKind(kind: string) { throw new Error(`Property only available for ${kind} models.`); } export function atomicProperty<T>(p: (location: StructureElement<Unit.Atomic>) => T) { - return property(l => Unit.isAtomic(l.unit) ? p(l as StructureElement<Unit.Atomic>) : _wrongUnitKind('atomic') ); + return property(l => Unit.isAtomic(l.unit) ? p(l as StructureElement<Unit.Atomic>) : _wrongUnitKind('atomic')); } export function coarseProperty<T>(p: (location: StructureElement<Unit.Spheres | Unit.Gaussians>) => T) { - return property(l => Unit.isCoarse(l.unit) ? p(l as StructureElement<Unit.Spheres | Unit.Gaussians>) : _wrongUnitKind('coarse') ); + return property(l => Unit.isCoarse(l.unit) ? p(l as StructureElement<Unit.Spheres | Unit.Gaussians>) : _wrongUnitKind('coarse')); } /** Represents multiple element index locations */ @@ -240,6 +243,30 @@ namespace StructureElement { return { box: boundaryHelper.getBox(), sphere: boundaryHelper.getSphere() }; } + + export function toScriptExpression(loci: Loci) { + if (loci.structure.models.length > 1) { + console.warn('toScriptExpression is only supported for Structure with single model, returning empty expression.'); + return MS.struct.generator.empty(); + } + const sourceIndices = UniqueArray.create<number, number>(); + const el = StructureElement.create(), p = StructureProperties.atom.sourceIndex; + for (const e of loci.elements) { + const { indices } = e; + const { elements } = e.unit; + + el.unit = e.unit; + for (let i = 0, _i = OrderedSet.size(indices); i < _i; i++) { + el.element = elements[OrderedSet.getAt(indices, i)]; + const idx = p(el); + UniqueArray.add(sourceIndices, idx, idx); + } + } + return MS.struct.generator.atomGroups({ + 'atom-test': MS.core.set.has([MS.set.apply(null, sourceIndices.array), MS.struct.atomProperty.core.sourceIndex()]), + 'group-by': 0 + }); + } } } diff --git a/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts b/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts index d39eda8b0..86476d4b9 100644 --- a/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts +++ b/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts @@ -4,22 +4,23 @@ * @author David Sehnal <david.sehnal@gmail.com> */ +import CIF from 'mol-io/reader/cif'; +import { Box3D } from 'mol-math/geometry'; +import { Vec3 } from 'mol-math/linear-algebra'; +import { volumeFromDensityServerData } from 'mol-model-formats/volume/density-server'; +import { StructureElement } from 'mol-model/structure'; +import { VolumeData, VolumeIsoValue } from 'mol-model/volume'; import { PluginBehavior } from 'mol-plugin/behavior'; +import { PluginContext } from 'mol-plugin/context'; import { PluginStateObject } from 'mol-plugin/state/objects'; -import { ParamDefinition as PD } from 'mol-util/param-definition'; -import { VolumeServerInfo, VolumeServerHeader } from './model'; import { createIsoValueParam } from 'mol-repr/volume/isosurface'; -import { VolumeIsoValue, VolumeData } from 'mol-model/volume'; import { Color } from 'mol-util/color'; -import { Vec3 } from 'mol-math/linear-algebra'; -import { PluginContext } from 'mol-plugin/context'; import { LRUCache } from 'mol-util/lru-cache'; -import CIF from 'mol-io/reader/cif'; -import { Box3D } from 'mol-math/geometry'; +import { ParamDefinition as PD } from 'mol-util/param-definition'; import { urlCombine } from 'mol-util/url'; -import { volumeFromDensityServerData } from 'mol-model-formats/volume/density-server'; -import { StructureElement } from 'mol-model/structure'; +import { VolumeServerHeader, VolumeServerInfo } from './model'; import { CreateVolumeStreamingBehavior } from './transformers'; +import { ButtonsType } from 'mol-util/input/input-observer'; export class VolumeStreaming extends PluginStateObject.CreateBehavior<VolumeStreaming.Behavior>({ name: 'Volume Streaming' }) { } @@ -147,8 +148,8 @@ export namespace VolumeStreaming { register(ref: string): void { // this.ref = ref; - this.subscribeObservable(this.plugin.events.canvas3d.click, ({ current }) => { - if (this.params.view.name !== 'selection-box') return; + this.subscribeObservable(this.plugin.events.canvas3d.click, ({ current, buttons }) => { + if (buttons !== ButtonsType.Flag.Secondary || this.params.view.name !== 'selection-box') return; // TODO: support link loci as well? // Perhaps structure loci too? if (!StructureElement.isLoci(current.loci)) return; @@ -198,7 +199,7 @@ export namespace VolumeStreaming { break; } - const data = emptyData ? { } : await this.queryData(box); + const data = emptyData ? {} : await this.queryData(box); if (!data) return false; diff --git a/src/mol-script/language/symbol-table/structure-query.ts b/src/mol-script/language/symbol-table/structure-query.ts index 6e345445a..1d87ccf8a 100644 --- a/src/mol-script/language/symbol-table/structure-query.ts +++ b/src/mol-script/language/symbol-table/structure-query.ts @@ -150,6 +150,10 @@ const modifier = { 'as-whole-residues': Argument(Type.Bool, { isOptional: true }) }), Types.ElementSelectionQuery, 'Pick all atom sets that are connected to the target.'), + wholeResidues: symbol(Arguments.Dictionary({ + 0: Argument(Types.ElementSelectionQuery), + }), Types.ElementSelectionQuery, 'Expand the selection to whole residues.'), + expandProperty: symbol(Arguments.Dictionary({ 0: Argument(Types.ElementSelectionQuery), property: Argument(Type.AnyValue) diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts index 2b6b45dcf..bbe87566e 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/src/mol-script/runtime/query/table.ts @@ -195,6 +195,19 @@ const symbols = [ groupBy: xs['group-by'] })(ctx)), + D(MolScript.structureQuery.generator.all, (ctx) => Queries.generators.all(ctx)), + D(MolScript.structureQuery.generator.empty, (ctx) => Queries.generators.none(ctx)), + + // ============= MODIFIERS ================ + + D(MolScript.structureQuery.modifier.includeSurroundings, (ctx, xs) => Queries.modifiers.includeSurroundings(xs[0] as any, { + radius: xs['radius'](ctx), + wholeResidues: !!(xs['as-whole-residues'] && xs['as-whole-residues'](ctx)), + elementRadius: xs['atom-radius'] + })(ctx)), + D(MolScript.structureQuery.modifier.wholeResidues, (ctx, xs) => Queries.modifiers.wholeResidues(xs[0] as any)(ctx)), + D(MolScript.structureQuery.modifier.expandProperty, (ctx, xs) => Queries.modifiers.expandProperty(xs[0] as any, xs['property'])(ctx)), + // ============= ATOM PROPERTIES ================ // ~~~ CORE ~~~ -- GitLab