|
@@ -6,11 +6,13 @@
|
|
|
|
|
|
import Query from './query'
|
|
|
import Selection from './selection'
|
|
|
-import * as P from './properties'
|
|
|
+import P from './properties'
|
|
|
import { Structure, AtomSet, Atom } from '../structure'
|
|
|
import { OrderedSet, Segmentation } from 'mol-base/collections/integer'
|
|
|
|
|
|
-export interface AtomGroupsSpec {
|
|
|
+export const all: Query = s => s;
|
|
|
+
|
|
|
+export interface AtomGroupsParams {
|
|
|
entityTest: Atom.Predicate,
|
|
|
chainTest: Atom.Predicate,
|
|
|
residueTest: Atom.Predicate,
|
|
@@ -18,21 +20,19 @@ export interface AtomGroupsSpec {
|
|
|
groupBy: Atom.Property<any>
|
|
|
}
|
|
|
|
|
|
-export const all: Query = s => s;
|
|
|
+export function atoms(params?: Partial<AtomGroupsParams>): Query {
|
|
|
+ if (!params || (!params.atomTest && !params.residueTest && !params.chainTest && !params.entityTest && !params.groupBy)) return all;
|
|
|
+ if (!!params.atomTest && !params.residueTest && !params.chainTest && !params.entityTest && !params.groupBy) return atomGroupsLinear(params.atomTest);
|
|
|
|
|
|
-export function atomGroups(spec?: Partial<AtomGroupsSpec>): Query {
|
|
|
- if (!spec || (!spec.atomTest && !spec.residueTest && !spec.chainTest && !spec.entityTest && !spec.groupBy)) return all;
|
|
|
- if (!!spec.atomTest && !spec.residueTest && !spec.chainTest && !spec.entityTest && !spec.groupBy) return atomGroupsLinear(spec.atomTest);
|
|
|
-
|
|
|
- const normalized: AtomGroupsSpec = {
|
|
|
- entityTest: spec.entityTest || P.constant.true,
|
|
|
- chainTest: spec.entityTest || P.constant.true,
|
|
|
- residueTest: spec.residueTest || P.constant.true,
|
|
|
- atomTest: spec.atomTest || P.constant.true,
|
|
|
- groupBy: spec.entityTest || P.constant.zero,
|
|
|
+ const normalized: AtomGroupsParams = {
|
|
|
+ entityTest: params.entityTest || P.constant.true,
|
|
|
+ chainTest: params.chainTest || P.constant.true,
|
|
|
+ residueTest: params.residueTest || P.constant.true,
|
|
|
+ atomTest: params.atomTest || P.constant.true,
|
|
|
+ groupBy: params.groupBy || P.constant.zero,
|
|
|
};
|
|
|
|
|
|
- if (!spec.groupBy) return atomGroupsSegmented(normalized)
|
|
|
+ if (!params.groupBy) return atomGroupsSegmented(normalized)
|
|
|
return atomGroupsGrouped(normalized);
|
|
|
}
|
|
|
|
|
@@ -60,7 +60,7 @@ function atomGroupsLinear(atomTest: Atom.Predicate): Query {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
-function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: AtomGroupsSpec): Query {
|
|
|
+function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: AtomGroupsParams): Query {
|
|
|
return structure => {
|
|
|
const { atoms, units } = structure;
|
|
|
const unitIds = AtomSet.unitIds(atoms);
|
|
@@ -151,8 +151,43 @@ class LinearGroupingBuilder {
|
|
|
constructor(private structure: Structure) { }
|
|
|
}
|
|
|
|
|
|
-function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, groupBy }: AtomGroupsSpec): Query {
|
|
|
+function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, groupBy }: AtomGroupsParams): Query {
|
|
|
return structure => {
|
|
|
- throw 'nyi'
|
|
|
+ const { atoms, units } = structure;
|
|
|
+ const unitIds = AtomSet.unitIds(atoms);
|
|
|
+ const l = Atom.Location();
|
|
|
+ const builder = new LinearGroupingBuilder(structure);
|
|
|
+
|
|
|
+ for (let i = 0, _i = unitIds.length; i < _i; i++) {
|
|
|
+ const unitId = unitIds[i];
|
|
|
+ const unit = units[unitId];
|
|
|
+ l.unit = unit;
|
|
|
+ const set = AtomSet.unitGetByIndex(atoms, i);
|
|
|
+
|
|
|
+ const chainsIt = Segmentation.transientSegments(unit.hierarchy.chainSegments, set);
|
|
|
+ const residuesIt = Segmentation.transientSegments(unit.hierarchy.residueSegments, set);
|
|
|
+ while (chainsIt.hasNext) {
|
|
|
+ const chainSegment = chainsIt.move();
|
|
|
+ l.atom = OrderedSet.getAt(set, chainSegment.start);
|
|
|
+ // test entity and chain
|
|
|
+ if (!entityTest(l) || !chainTest(l)) continue;
|
|
|
+
|
|
|
+ residuesIt.setSegment(chainSegment);
|
|
|
+ while (residuesIt.hasNext) {
|
|
|
+ const residueSegment = residuesIt.move();
|
|
|
+ l.atom = OrderedSet.getAt(set, residueSegment.start);
|
|
|
+
|
|
|
+ // test residue
|
|
|
+ if (!residueTest(l)) continue;
|
|
|
+
|
|
|
+ for (let j = residueSegment.start, _j = residueSegment.end; j < _j; j++) {
|
|
|
+ l.atom = OrderedSet.getAt(set, j);
|
|
|
+ if (atomTest(l)) builder.add(groupBy(l), unitId, l.atom);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return builder.getSelection();
|
|
|
};
|
|
|
}
|