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

proteopedia wrapper

parent 7437e8c9
No related branches found
No related tags found
No related merge requests found
......@@ -111,5 +111,7 @@ export enum StateElements {
HetVisual = 'het-visual',
Het3DSNFG = 'het-3dsnfg',
Water = 'water',
WaterVisual = 'water-visual'
WaterVisual = 'water-visual',
HetGroupFocus = 'het-group-focus'
}
\ No newline at end of file
......@@ -99,6 +99,7 @@
PluginWrapper.events.modelInfo.subscribe(function (info) {
console.log('Model Info', info);
listHetGroups(info);
});
addControl('Load Asym Unit', () => PluginWrapper.load({ url: url, format: format }));
......@@ -145,6 +146,12 @@
addControl('Apply Evo Cons', () => PluginWrapper.coloring.evolutionaryConservation());
addControl('Default Visuals', () => PluginWrapper.updateStyle());
addSeparator();
addHeader('HET Groups');
addControl('Reset', () => PluginWrapper.hetGroups.reset());
addHetGroupsContainer();
addSeparator();
addHeader('State');
......@@ -163,6 +170,12 @@
////////////////////////////////////////////////////////
function addHetGroupsContainer() {
var div = document.createElement('div');
div.id = 'het-groups';
$('controls').appendChild(div);
}
function addControl(label, action) {
var btn = document.createElement('button');
btn.onclick = action;
......@@ -180,6 +193,19 @@
h.innerText = header;
$('controls').appendChild(h);
}
function listHetGroups(info) {
var div = $('het-groups');
div.innerHTML = '';
info.hetResidues.forEach(function (r) {
var l = document.createElement('button');
l.innerText = r.name;
l.onclick = function () {
PluginWrapper.hetGroups.focusFirst(r.name);
};
div.appendChild(l);
});
}
</script>
</body>
</html>
\ No newline at end of file
......@@ -21,6 +21,14 @@ import { ControlsWrapper } from './ui/controls';
import { PluginState } from 'mol-plugin/state';
import { Scheduler } from 'mol-task';
import { createProteopediaCustomTheme } from './coloring';
import { MolScriptBuilder as MS } from 'mol-script/language/builder';
import { BuiltInStructureRepresentations } from 'mol-repr/structure/registry';
import { BuiltInColorThemes } from 'mol-theme/color';
import { BuiltInSizeThemes } from 'mol-theme/size';
import { ColorNames } from 'mol-util/color/tables';
// import { Vec3 } from 'mol-math/linear-algebra';
// import { ParamDefinition } from 'mol-util/param-definition';
// import { Text } from 'mol-geo/geometry/text/text';
require('mol-plugin/skin/light.scss')
class MolStarProteopediaWrapper {
......@@ -257,6 +265,69 @@ class MolStarProteopediaWrapper {
}
}
hetGroups = {
reset: () => {
const update = this.state.build().delete(StateElements.HetGroupFocus);
PluginCommands.State.Update.dispatch(this.plugin, { state: this.state, tree: update });
PluginCommands.Camera.Reset.dispatch(this.plugin, { });
},
focusFirst: async (resn: string) => {
if (!this.state.transforms.has(StateElements.Assembly)) return;
// const asm = (this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure).data;
const update = this.state.build();
update.delete(StateElements.HetGroupFocus);
const surroundings = MS.struct.modifier.includeSurroundings({
0: MS.struct.filter.first([
MS.struct.generator.atomGroups({
'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), resn]),
'group-by': MS.struct.atomProperty.macromolecular.residueKey()
})
]),
radius: 5,
'as-whole-residues': true
});
const sel = update.to(StateElements.Assembly)
.apply(StateTransforms.Model.StructureSelection, { label: resn, query: surroundings }, { ref: StateElements.HetGroupFocus });
sel.apply(StateTransforms.Representation.StructureRepresentation3D, this.createSurVisualParams());
// sel.apply(StateTransforms.Representation.StructureLabels3D, {
// target: { name: 'residues', params: { } },
// options: {
// ...ParamDefinition.getDefaultValues(Text.Params),
// background: true,
// backgroundMargin: 0.2,
// backgroundColor: ColorNames.snow,
// backgroundOpacity: 0.9,
// }
// });
await PluginCommands.State.Update.dispatch(this.plugin, { state: this.state, tree: update });
const focus = (this.state.select(StateElements.HetGroupFocus)[0].obj as PluginStateObject.Molecule.Structure).data;
const sphere = focus.boundary.sphere;
// const asmCenter = asm.boundary.sphere.center;
// const position = Vec3.sub(Vec3.zero(), sphere.center, asmCenter);
// Vec3.normalize(position, position);
// Vec3.scaleAndAdd(position, sphere.center, position, sphere.radius);
const snapshot = this.plugin.canvas3d.camera.getFocus(sphere.center, 0.75 * sphere.radius);
PluginCommands.Camera.SetSnapshot.dispatch(this.plugin, { snapshot, durationMs: 250 });
}
}
private createSurVisualParams() {
const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure;
return StructureRepresentation3DHelpers.createParams(this.plugin, asm.data, {
repr: BuiltInStructureRepresentations['ball-and-stick'],
color: [BuiltInColorThemes.uniform, () => ({ value: ColorNames.gray })],
size: [BuiltInSizeThemes.uniform, () => ({ value: 0.33 } )]
});
}
snapshot = {
get: () => {
return this.plugin.state.getSnapshot();
......
......@@ -84,7 +84,7 @@ class Camera implements Object3D {
return ret;
}
focus(target: Vec3, radius: number) {
getFocus(target: Vec3, radius: number): Partial<Camera.Snapshot> {
const fov = this.state.fov
const { width, height } = this.viewport
const aspect = width / height
......@@ -98,7 +98,11 @@ class Camera implements Object3D {
if (currentDistance < targetDistance) Vec3.negate(this.deltaDirection, this.deltaDirection)
Vec3.add(this.newPosition, this.state.position, this.deltaDirection)
this.setState({ target, position: this.newPosition })
return { target, position: Vec3.clone(this.newPosition) };
}
focus(target: Vec3, radius: number) {
this.setState(this.getFocus(target, radius));
}
// lookAt(target: Vec3) {
......
......@@ -9,12 +9,14 @@ import { StructureQuery } from './query/query'
export * from './query/context'
import * as generators from './query/queries/generators'
import * as modifiers from './query/queries/modifiers'
import * as filters from './query/queries/filters'
import * as combinators from './query/queries/combinators'
import * as internal from './query/queries/internal'
import pred from './query/predicates'
export const Queries = {
generators,
filters,
modifiers,
combinators,
pred,
......
......@@ -31,6 +31,25 @@ export function pick(query: StructureQuery, pred: QueryPredicate): StructureQuer
};
}
export function first(query: StructureQuery): StructureQuery {
return ctx => {
const sel = query(ctx);
const ret = StructureSelection.LinearBuilder(ctx.inputStructure);
if (sel.kind === 'singletons') {
if (sel.structure.elementCount > 0) {
const u = sel.structure.units[0];
const s = Structure.create([u.getChild(SortedArray.ofSingleton(u.elements[0]))]);
ret.add(s);
}
} else {
if (sel.structures.length > 0) {
ret.add(sel.structures[0]);
}
}
return ret.getSelection();
};
}
export interface UnitTypeProperties { atomic?: QueryFn, coarse?: QueryFn }
export function getCurrentStructureProperties(ctx: QueryContext, props: UnitTypeProperties, set: Set<any>) {
......
......@@ -53,7 +53,7 @@ export const PluginCommands = {
},
Camera: {
Reset: PluginCommand<{}>(),
SetSnapshot: PluginCommand<{ snapshot: Camera.Snapshot, durationMs?: number }>(),
SetSnapshot: PluginCommand<{ snapshot: Partial<Camera.Snapshot>, durationMs?: number }>(),
Snapshots: {
Add: PluginCommand<{ name?: string, description?: string }>(),
Remove: PluginCommand<{ id: string }>(),
......
......@@ -167,6 +167,10 @@ const filter = {
test: Argument(Type.Bool)
}), Types.ElementSelectionQuery, 'Pick all atom sets that satisfy the test.'),
first: symbol(Arguments.Dictionary({
0: Argument(Types.ElementSelectionQuery)
}), Types.ElementSelectionQuery, 'Take the 1st atom set in the sequence.'),
withSameAtomProperties: symbol(Arguments.Dictionary({
0: Argument(Types.ElementSelectionQuery),
source: Argument(Types.ElementSelectionQuery),
......
......@@ -186,6 +186,9 @@ const symbols = [
C(MolScript.structureQuery.slot.element, (ctx, _) => ctx.element),
// C(MolScript.structureQuery.slot.elementSetReduce, (ctx, _) => ctx.element),
// ============= FILTERS ================
D(MolScript.structureQuery.filter.first, (ctx, xs) => Queries.filters.first(xs[0] as any)(ctx)),
// ============= GENERATORS ================
D(MolScript.structureQuery.generator.atomGroups, (ctx, xs) => Queries.generators.atoms({
entityTest: xs['entity-test'],
......
......@@ -148,6 +148,7 @@ export const SymbolTable = [
[
'Filters',
Alias(MolScript.structureQuery.filter.pick, 'sel.atom.pick'),
Alias(MolScript.structureQuery.filter.first, 'sel.atom.first'),
Alias(MolScript.structureQuery.filter.withSameAtomProperties, 'sel.atom.with-same-atom-properties'),
Alias(MolScript.structureQuery.filter.intersectedBy, 'sel.atom.intersected-by'),
Alias(MolScript.structureQuery.filter.within, 'sel.atom.within'),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment