molstar
Version:
A comprehensive macromolecular library.
299 lines • 12.2 kB
JavaScript
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { SetUtils } from '../../../../mol-util/set';
import { Unit } from '../../structure';
import { StructureSelection } from '../selection';
import { structureAreIntersecting } from '../utils/structure-set';
import { Vec3 } from '../../../../mol-math/linear-algebra';
import { checkStructureMaxRadiusDistance, checkStructureMinMaxDistance } from '../utils/structure-distance';
import { Structure } from '../../structure/structure';
import { SortedArray } from '../../../../mol-data/int';
export function pick(query, pred) {
return function (ctx) {
var sel = query(ctx);
var ret = StructureSelection.LinearBuilder(ctx.inputStructure);
ctx.pushCurrentElement();
StructureSelection.forEach(sel, function (s, i) {
ctx.currentStructure = s;
if (pred(ctx))
ret.add(s);
if (i % 100)
ctx.throwIfTimedOut();
});
ctx.popCurrentStructure();
return ret.getSelection();
};
}
export function first(query) {
return function (ctx) {
var sel = query(ctx);
var ret = StructureSelection.LinearBuilder(ctx.inputStructure);
if (sel.kind === 'singletons') {
if (sel.structure.elementCount > 0) {
var u = sel.structure.units[0];
var s = Structure.create([u.getChild(SortedArray.ofSingleton(u.elements[0]))], { parent: ctx.inputStructure });
ret.add(s);
}
}
else {
if (sel.structures.length > 0) {
ret.add(sel.structures[0]);
}
}
return ret.getSelection();
};
}
export function getCurrentStructureProperties(ctx, props, set) {
var units = ctx.currentStructure.units;
var l = ctx.pushCurrentElement();
l.structure = ctx.currentStructure;
for (var _a = 0, units_1 = units; _a < units_1.length; _a++) {
var unit = units_1[_a];
l.unit = unit;
var elements = unit.elements;
var fn = void 0;
if (Unit.isAtomic(unit))
fn = props.atomic;
else
fn = props.coarse;
if (!fn)
continue;
for (var j = 0, _j = elements.length; j < _j; j++) {
l.element = elements[j];
set.add(fn(ctx));
}
ctx.throwIfTimedOut();
}
ctx.popCurrentElement();
return set;
}
function getSelectionProperties(ctx, query, props) {
var set = new Set();
var sel = query(ctx);
ctx.pushCurrentElement();
StructureSelection.forEach(sel, function (s, i) {
ctx.currentStructure = s;
getCurrentStructureProperties(ctx, props, set);
if (i % 10)
ctx.throwIfTimedOut();
});
ctx.popCurrentElement();
return set;
}
export function withSameAtomProperties(query, propertySource, props) {
return function (ctx) {
var sel = query(ctx);
var propSet = getSelectionProperties(ctx, propertySource, props);
var ret = StructureSelection.LinearBuilder(ctx.inputStructure);
ctx.pushCurrentStructure();
StructureSelection.forEach(sel, function (s, i) {
ctx.currentStructure = s;
var currentProps = getCurrentStructureProperties(ctx, props, new Set());
if (SetUtils.isSuperset(currentProps, propSet)) {
ret.add(s);
}
if (i % 10)
ctx.throwIfTimedOut();
});
ctx.popCurrentStructure();
return ret.getSelection();
};
}
export function areIntersectedBy(query, by) {
return function (ctx) {
var mask = StructureSelection.unionStructure(by(ctx));
var ret = StructureSelection.LinearBuilder(ctx.inputStructure);
StructureSelection.forEach(query(ctx), function (s, i) {
if (structureAreIntersecting(mask, s))
ret.add(s);
if (i % 10)
ctx.throwIfTimedOut();
});
return ret.getSelection();
};
}
export function within(params) {
return function (queryCtx) {
var ctx = {
queryCtx: queryCtx,
selection: params.query(queryCtx),
target: params.target(queryCtx),
maxRadius: params.maxRadius,
minRadius: params.minRadius ? Math.max(0, params.minRadius) : 0,
elementRadius: params.elementRadius,
invert: !!params.invert,
};
if (ctx.minRadius === 0 && typeof params.minRadius === 'undefined') {
return withinMaxRadiusLookup(ctx);
}
else if (ctx.minRadius === 0) {
return withinMaxRadius(ctx);
}
else {
return withinMinMaxRadius(ctx);
}
};
}
function withinMaxRadiusLookup(_a) {
var queryCtx = _a.queryCtx, selection = _a.selection, target = _a.target, maxRadius = _a.maxRadius, invert = _a.invert;
var targetLookup = StructureSelection.unionStructure(target).lookup3d;
var ret = StructureSelection.LinearBuilder(queryCtx.inputStructure);
var pos = Vec3.zero();
StructureSelection.forEach(selection, function (s, sI) {
var units = s.units;
var withinRadius = false;
for (var i = 0, _i = units.length; i < _i; i++) {
var unit = units[i];
var elements = unit.elements, _a = unit.conformation, position = _a.position, r = _a.r;
for (var i_1 = 0, _i_1 = elements.length; i_1 < _i_1; i_1++) {
var e = elements[i_1];
position(e, pos);
if (targetLookup.check(pos[0], pos[1], pos[2], maxRadius + r(e))) {
withinRadius = true;
break;
}
}
if (withinRadius)
break;
}
if (invert)
withinRadius = !withinRadius;
if (withinRadius)
ret.add(s);
if (sI % 10 === 0)
queryCtx.throwIfTimedOut();
});
return ret.getSelection();
}
function withinMaxRadius(_a) {
var queryCtx = _a.queryCtx, selection = _a.selection, target = _a.target, maxRadius = _a.maxRadius, invert = _a.invert, elementRadius = _a.elementRadius;
var targetStructure = StructureSelection.unionStructure(target);
var ret = StructureSelection.LinearBuilder(queryCtx.inputStructure);
queryCtx.pushCurrentElement();
StructureSelection.forEach(selection, function (s, sI) {
var withinRadius = checkStructureMaxRadiusDistance(queryCtx, targetStructure, s, maxRadius, elementRadius);
if (invert)
withinRadius = !withinRadius;
if (withinRadius)
ret.add(s);
if (sI % 10 === 0)
queryCtx.throwIfTimedOut();
});
queryCtx.popCurrentElement();
return ret.getSelection();
}
function withinMinMaxRadius(_a) {
var queryCtx = _a.queryCtx, selection = _a.selection, target = _a.target, minRadius = _a.minRadius, maxRadius = _a.maxRadius, invert = _a.invert, elementRadius = _a.elementRadius;
var targetStructure = StructureSelection.unionStructure(target);
var ret = StructureSelection.LinearBuilder(queryCtx.inputStructure);
queryCtx.pushCurrentElement();
StructureSelection.forEach(selection, function (s, sI) {
var withinRadius = checkStructureMinMaxDistance(queryCtx, targetStructure, s, minRadius, maxRadius, elementRadius);
if (invert)
withinRadius = !withinRadius;
if (withinRadius)
ret.add(s);
if (sI % 10 === 0)
queryCtx.throwIfTimedOut();
});
queryCtx.popCurrentElement();
return ret.getSelection();
}
function checkConnected(ctx, structure) {
var queryCtx = ctx.queryCtx, input = ctx.input, target = ctx.target, disjunct = ctx.disjunct;
var atomicBond = queryCtx.atomicBond;
var interBonds = input.interUnitBonds;
atomicBond.setStructure(input);
for (var _a = 0, _b = structure.units; _a < _b.length; _a++) {
var unit = _b[_a];
if (!Unit.isAtomic(unit))
continue;
var inputUnit = input.unitMap.get(unit.id);
var _c = inputUnit.bonds, offset = _c.offset, b = _c.b, _d = _c.edgeProps, flags = _d.flags, order = _d.order;
var bondedUnits = interBonds.getConnectedUnits(unit.id);
var buCount = bondedUnits.length;
var srcElements = unit.elements;
var inputElements = inputUnit.elements;
for (var i = 0, _i = srcElements.length; i < _i; i++) {
var inputIndex = SortedArray.indexOf(inputElements, srcElements[i]);
atomicBond.a.unit = inputUnit;
atomicBond.b.unit = inputUnit;
// tElement.unit = unit;
for (var l = offset[inputIndex], _l = offset[inputIndex + 1]; l < _l; l++) {
// tElement.element = inputElements[b[l]];
atomicBond.b.element = inputUnit.elements[b[l]];
if (disjunct && SortedArray.has(unit.elements, atomicBond.b.element))
continue;
if (!target.hasElement(atomicBond.b))
continue;
atomicBond.aIndex = inputIndex;
atomicBond.a.element = srcElements[i];
atomicBond.bIndex = b[l];
atomicBond.type = flags[l];
atomicBond.order = order[l];
if (atomicBond.test(queryCtx, true))
return true;
}
for (var li = 0; li < buCount; li++) {
var lu = bondedUnits[li];
var bUnit = input.unitMap.get(lu.unitB);
var bElements = bUnit.elements;
var bonds = lu.getEdges(inputIndex);
for (var bi = 0, _bi = bonds.length; bi < _bi; bi++) {
var bond = bonds[bi];
atomicBond.b.unit = bUnit;
atomicBond.b.element = bElements[bond.indexB];
if (!target.hasElement(atomicBond.b))
continue;
if (disjunct && structure.hasElement(atomicBond.b))
continue;
atomicBond.a.unit = inputUnit;
atomicBond.aIndex = inputIndex;
atomicBond.a.element = srcElements[i];
atomicBond.bIndex = bond.indexB;
atomicBond.type = bond.props.flag;
atomicBond.order = bond.props.order;
if (atomicBond.test(queryCtx, true))
return true;
}
}
}
}
return false;
}
export function isConnectedTo(_a) {
var query = _a.query, target = _a.target, disjunct = _a.disjunct, invert = _a.invert, bondTest = _a.bondTest;
return function (ctx) {
var targetSel = target(ctx);
if (StructureSelection.isEmpty(targetSel))
return targetSel;
var selection = query(ctx);
if (StructureSelection.isEmpty(selection))
return selection;
var connCtx = {
queryCtx: ctx,
input: ctx.inputStructure,
disjunct: disjunct,
target: StructureSelection.unionStructure(targetSel)
};
var ret = StructureSelection.LinearBuilder(ctx.inputStructure);
ctx.pushCurrentBond();
ctx.atomicBond.setTestFn(bondTest);
StructureSelection.forEach(selection, function (s, sI) {
if (checkConnected(connCtx, s)) {
ret.add(s);
}
else if (invert) {
ret.add(s);
}
if (sI % 5 === 0)
ctx.throwIfTimedOut();
});
ctx.popCurrentBond();
return ret.getSelection();
};
}
//# sourceMappingURL=filters.js.map