Skip to content
Snippets Groups Projects
Commit 6217a51f authored by Alexander Rose's avatar Alexander Rose
Browse files

optimized `toScriptExpression`

parent f1edb05c
No related branches found
No related tags found
No related merge requests found
...@@ -16,7 +16,7 @@ import Structure from './structure'; ...@@ -16,7 +16,7 @@ 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 { sortArray, hashFnv32a, hash2 } from '../../../mol-data/util';
import Expression from '../../../mol-script/language/expression'; import Expression from '../../../mol-script/language/expression';
interface StructureElement<U = Unit> { interface StructureElement<U = Unit> {
...@@ -358,21 +358,81 @@ namespace StructureElement { ...@@ -358,21 +358,81 @@ namespace StructureElement {
} }
} }
const byOpName: Expression[] = []; const opData: OpData[] = [];
const keys = sourceIndexMap.keys(); const keys = sourceIndexMap.keys();
while (true) { while (true) {
const k = keys.next(); const k = keys.next();
if (k.done) break; if (k.done) break;
const e = sourceIndexMap.get(k.value)!; const e = sourceIndexMap.get(k.value)!;
byOpName.push(getOpNameQuery(k.value, e.xs.array, models.length > 1, e.modelLabel, e.modelIndex)); opData.push(getOpData(k.value, e.xs.array, models.length > 1, e.modelLabel, e.modelIndex));
} }
const opGroups = new Map<string, OpData>();
for (let i = 0, il = opData.length; i < il; ++i) {
const d = opData[i]
const hash = hash2(hashFnv32a(d.atom.ranges), hashFnv32a(d.atom.set))
const key = `${hash}|${d.entity ? (d.entity.modelLabel + d.entity.modelIndex) : ''}`
if (opGroups.has(key)) {
opGroups.get(key)!.chain.opName.push(...d.chain.opName)
} else {
opGroups.set(key, d)
}
}
const opQueries: Expression[] = [];
opGroups.forEach(d => {
const { ranges, set } = d.atom
const { opName } = d.chain
const opProp = MS.struct.atomProperty.core.operatorName()
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]]);
}
if (d.entity) {
const { modelLabel, modelIndex } = d.entity
opQueries.push(MS.struct.generator.atomGroups({
'atom-test': tests.length > 1 ? MS.core.logic.or(tests) : tests[0],
'chain-test': opName.length > 1
? MS.core.set.has([MS.set.apply(null, opName), opProp])
: MS.core.rel.eq([opProp, opName[0]]),
'entity-test': MS.core.logic.and([
MS.core.rel.eq([MS.struct.atomProperty.core.modelLabel(), modelLabel]),
MS.core.rel.eq([MS.struct.atomProperty.core.modelIndex(), modelIndex]),
])
}))
} else {
opQueries.push(MS.struct.generator.atomGroups({
'atom-test': tests.length > 1 ? MS.core.logic.or(tests) : tests[0],
'chain-test': opName.length > 1
? MS.core.set.has([MS.set.apply(null, opName), opProp])
: MS.core.rel.eq([opProp, opName[0]])
}))
}
})
return MS.struct.modifier.union([ return MS.struct.modifier.union([
byOpName.length === 1 ? byOpName[0] : MS.struct.combinator.merge(byOpName) opQueries.length === 1
? opQueries[0]
// Need to union before merge for fast performance
: MS.struct.combinator.merge(opQueries.map(q => MS.struct.modifier.union([ q ])))
]); ]);
} }
function getOpNameQuery(opName: string, xs: number[], multimodel: boolean, modelLabel: string, modelIndex: number) { type OpData = {
atom: { set: number[], ranges: number[] },
chain: { opName: string[] },
entity?: { modelLabel: string, modelIndex: number }
}
function getOpData(opName: string, xs: number[], multimodel: boolean, modelLabel: string, modelIndex: number): OpData {
sortArray(xs); sortArray(xs);
const ranges: number[] = []; const ranges: number[] = [];
...@@ -395,30 +455,17 @@ namespace StructureElement { ...@@ -395,30 +455,17 @@ namespace StructureElement {
} }
} }
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 multimodel return multimodel
? MS.struct.generator.atomGroups({ ? {
'atom-test': tests.length > 1 ? MS.core.logic.or(tests) : tests[0], atom: { set, ranges },
'chain-test': MS.core.rel.eq([MS.struct.atomProperty.core.operatorName(), opName]), chain: { opName: [ opName ] },
'entity-test': MS.core.logic.and([ entity: { modelLabel, modelIndex }
MS.core.rel.eq([MS.struct.atomProperty.core.modelLabel(), modelLabel]), }
MS.core.rel.eq([MS.struct.atomProperty.core.modelIndex(), modelIndex]), : {
]) atom: { set, ranges },
}) chain: { opName: [ opName ] },
: MS.struct.generator.atomGroups({ }
'atom-test': tests.length > 1 ? MS.core.logic.or(tests) : tests[0],
'chain-test': MS.core.rel.eq([MS.struct.atomProperty.core.operatorName(), opName])
});
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment