Skip to content
Snippets Groups Projects
Commit 28fab6a5 authored by David Sehnal's avatar David Sehnal
Browse files

mol-plugin: create structure from selection, better element loci to query translation

parent c1627292
No related branches found
No related tags found
No related merge requests found
...@@ -15,6 +15,8 @@ import Structure from './structure'; ...@@ -15,6 +15,8 @@ import Structure from './structure';
import Unit from './unit'; import Unit from './unit';
import { Boundary } from './util/boundary'; import { Boundary } from './util/boundary';
import { StructureProperties } from '../structure'; import { StructureProperties } from '../structure';
import { sortArray } from 'mol-data/util';
import Expression from 'mol-script/language/expression';
interface StructureElement<U = Unit> { interface StructureElement<U = Unit> {
readonly kind: 'element-location', readonly kind: 'element-location',
...@@ -249,6 +251,8 @@ namespace StructureElement { ...@@ -249,6 +251,8 @@ namespace StructureElement {
console.warn('toScriptExpression is only supported for Structure with single model, returning empty expression.'); console.warn('toScriptExpression is only supported for Structure with single model, returning empty expression.');
return MS.struct.generator.empty(); return MS.struct.generator.empty();
} }
if (loci.elements.length === 0) return MS.struct.generator.empty();
const sourceIndices = UniqueArray.create<number, number>(); const sourceIndices = UniqueArray.create<number, number>();
const el = StructureElement.create(), p = StructureProperties.atom.sourceIndex; const el = StructureElement.create(), p = StructureProperties.atom.sourceIndex;
for (const e of loci.elements) { for (const e of loci.elements) {
...@@ -262,8 +266,43 @@ namespace StructureElement { ...@@ -262,8 +266,43 @@ namespace StructureElement {
UniqueArray.add(sourceIndices, idx, idx); UniqueArray.add(sourceIndices, idx, idx);
} }
} }
const xs = sourceIndices.array;
sortArray(xs);
const ranges: number[] = [];
const set: number[] = [];
let i = 0, len = xs.length;
while (i < len) {
const start = i;
i++;
while (i < len && xs[i - 1] + 1 === xs[i]) i++;
const end = i;
// TODO: is this a good value?
if (end - start > 12) {
ranges[ranges.length] = xs[start];
ranges[ranges.length] = xs[end - 1];
} else {
for (let j = start; j < end; j++) {
set[set.length] = xs[j];
}
}
}
const siProp = MS.struct.atomProperty.core.sourceIndex();
const tests: Expression[] = [];
// TODO: add set.ofRanges constructor to MolQL???
if (set.length > 0) {
tests[tests.length] = MS.core.set.has([MS.set.apply(null, set), siProp]);
}
for (let rI = 0, _rI = ranges.length / 2; rI < _rI; rI++) {
tests[tests.length] = MS.core.rel.inRange([siProp, ranges[2 * rI], ranges[2 * rI + 1]]);
}
return MS.struct.generator.atomGroups({ return MS.struct.generator.atomGroups({
'atom-test': MS.core.set.has([MS.set.apply(null, sourceIndices.array), MS.struct.atomProperty.core.sourceIndex()]), 'atom-test': tests.length > 1 ? MS.core.logic.or.apply(null, tests) : tests[0],
'group-by': 0 'group-by': 0
}); });
} }
......
...@@ -47,6 +47,8 @@ export const DefaultPluginSpec: PluginSpec = { ...@@ -47,6 +47,8 @@ export const DefaultPluginSpec: PluginSpec = {
PluginSpec.Action(StateTransforms.Representation.StructureRepresentation3D), PluginSpec.Action(StateTransforms.Representation.StructureRepresentation3D),
PluginSpec.Action(StateTransforms.Representation.ExplodeStructureRepresentation3D), PluginSpec.Action(StateTransforms.Representation.ExplodeStructureRepresentation3D),
PluginSpec.Action(StateTransforms.Representation.VolumeRepresentation3D), PluginSpec.Action(StateTransforms.Representation.VolumeRepresentation3D),
PluginSpec.Action(StateActions.Structure.StructureFromSelection),
], ],
behaviors: [ behaviors: [
PluginSpec.Behavior(PluginBehaviors.Representation.HighlightLoci), PluginSpec.Behavior(PluginBehaviors.Representation.HighlightLoci),
......
...@@ -12,10 +12,11 @@ import { PluginStateObject } from '../objects'; ...@@ -12,10 +12,11 @@ import { PluginStateObject } from '../objects';
import { StateTransforms } from '../transforms'; import { StateTransforms } from '../transforms';
import { Download } from '../transforms/data'; import { Download } from '../transforms/data';
import { StructureRepresentation3DHelpers } from '../transforms/representation'; import { StructureRepresentation3DHelpers } from '../transforms/representation';
import { CustomModelProperties } from '../transforms/model'; import { CustomModelProperties, StructureSelection } from '../transforms/model';
import { DataFormatProvider } from './data-format'; import { DataFormatProvider } from './data-format';
import { FileInfo } from 'mol-util/file-info'; import { FileInfo } from 'mol-util/file-info';
import { Task } from 'mol-task'; import { Task } from 'mol-task';
import { StructureElement } from 'mol-model/structure';
export const MmcifProvider: DataFormatProvider<any> = { export const MmcifProvider: DataFormatProvider<any> = {
label: 'mmCIF', label: 'mmCIF',
...@@ -230,3 +231,21 @@ export const EnableModelCustomProps = StateAction.build({ ...@@ -230,3 +231,21 @@ export const EnableModelCustomProps = StateAction.build({
const root = state.build().to(ref).insert(CustomModelProperties, params); const root = state.build().to(ref).insert(CustomModelProperties, params);
return state.updateTree(root); return state.updateTree(root);
}); });
export const StructureFromSelection = StateAction.build({
display: { name: 'Selection Structure', description: 'Create a new Structure from the current selection.' },
from: PluginStateObject.Molecule.Structure,
params: {
label: PD.Text()
}
// isApplicable(a, t, ctx: PluginContext) {
// return t.transformer !== CustomModelProperties;
// }
})(({ a, ref, params, state }, plugin: PluginContext) => {
const sel = plugin.helpers.structureSelection.get(a.data);
if (sel.kind === 'empty-loci') return Task.constant('', void 0);
const query = StructureElement.Loci.toScriptExpression(sel);
const root = state.build().to(ref).apply(StructureSelection, { query, label: params.label });
return state.updateTree(root);
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment