Ver Fonte

add key to symmetry operator

- molql operatorKey
- index-pair operator prop
Alexander Rose há 2 anos atrás
pai
commit
ba50760f92

+ 12 - 9
src/mol-math/geometry/symmetry-operator.ts

@@ -1,11 +1,11 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 import { lerp as scalar_lerp } from '../../mol-math/interpolate';
-import { defaults } from '../../mol-util';
 import { Mat3 } from '../linear-algebra/3d/mat3';
 import { Mat4 } from '../linear-algebra/3d/mat4';
 import { Quat } from '../linear-algebra/3d/quat';
@@ -29,11 +29,13 @@ interface SymmetryOperator {
     readonly hkl: Vec3,
     /** spacegroup symmetry operator index, -1 if not applicable */
     readonly spgrOp: number,
+    /** unique (external) key, -1 if not available */
+    readonly key: number,
 
     readonly matrix: Mat4,
-    // cache the inverse of the transform
+    /** cache the inverse of the transform */
     readonly inverse: Mat4,
-    // optimize the identity case
+    /** optimize the identity case */
     readonly isIdentity: boolean,
 
     /**
@@ -51,19 +53,20 @@ namespace SymmetryOperator {
 
     export const RotationTranslationEpsilon = 0.005;
 
-    export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: number, hkl?: Vec3, spgrOp?: number }
+    export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: number, hkl?: Vec3, spgrOp?: number, key?: number }
     export function create(name: string, matrix: Mat4, info?: CreateInfo | SymmetryOperator): SymmetryOperator {
-        let { assembly, ncsId, hkl, spgrOp } = info || { };
+        let { assembly, ncsId, hkl, spgrOp, key } = info || { };
         const _hkl = hkl ? Vec3.clone(hkl) : Vec3();
-        spgrOp = defaults(spgrOp, -1);
+        spgrOp = spgrOp ?? -1;
+        key = key ?? -1;
         ncsId = ncsId || -1;
         const isIdentity = Mat4.isIdentity(matrix);
         const suffix = getSuffix(info, isIdentity);
-        if (isIdentity) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix };
+        if (isIdentity) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix, key };
         if (!Mat4.isRotationAndTranslation(matrix, RotationTranslationEpsilon)) {
             console.warn(`Symmetry operator (${name}) should be a composition of rotation and translation.`);
         }
-        return { name, assembly, matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp, ncsId, suffix };
+        return { name, assembly, matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp, key, ncsId, suffix };
     }
 
     function isSymmetryOperator(x: any): x is SymmetryOperator {

+ 11 - 2
src/mol-model-formats/structure/property/bonds/index-pair.ts

@@ -14,6 +14,8 @@ import { ElementIndex } from '../../../../mol-model/structure';
 
 export type IndexPairsProps = {
     readonly key: ArrayLike<number>
+    /** Sorted contor-paired operator keys */
+    readonly operator: ArrayLike<number>
     readonly order: ArrayLike<number>
     readonly distance: ArrayLike<number>
     readonly flag: ArrayLike<BondType.Flag>
@@ -24,18 +26,20 @@ export type IndexPairBonds = { bonds: IndexPairs, maxDistance: number }
 function getGraph(indexA: ArrayLike<ElementIndex>, indexB: ArrayLike<ElementIndex>, props: Partial<IndexPairsProps>, count: number): IndexPairs {
     const builder = new IntAdjacencyGraph.EdgeBuilder(count, indexA, indexB);
     const key = new Int32Array(builder.slotCount);
+    const operator = new Array(builder.slotCount);
     const order = new Int8Array(builder.slotCount);
     const distance = new Array(builder.slotCount);
     const flag = new Array(builder.slotCount);
     for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
         builder.addNextEdge();
         builder.assignProperty(key, props.key ? props.key[i] : -1);
+        builder.assignProperty(operator, props.operator ? props.operator[i] : -1);
         builder.assignProperty(order, props.order ? props.order[i] : 1);
         builder.assignProperty(distance, props.distance ? props.distance[i] : -1);
         builder.assignProperty(flag, props.flag ? props.flag[i] : BondType.Flag.Covalent);
     }
 
-    return builder.createGraph({ key, order, distance, flag });
+    return builder.createGraph({ key, operator, order, distance, flag });
 }
 
 export namespace IndexPairBonds {
@@ -50,6 +54,10 @@ export namespace IndexPairBonds {
             indexA: Column<number>,
             indexB: Column<number>,
             key?: Column<number>,
+            /**
+             * Sorted contor-paired operator keys. Used in bond computation.
+             */
+            operator?: Column<number>,
             order?: Column<number>,
             /**
              * Useful for bonds in periodic cells. That is, only bonds within the given
@@ -83,11 +91,12 @@ export namespace IndexPairBonds {
         const indexA = pairs.indexA.toArray() as ArrayLike<ElementIndex>;
         const indexB = pairs.indexB.toArray() as ArrayLike<ElementIndex>;
         const key = pairs.key && pairs.key.toArray();
+        const operator = pairs.operator && pairs.operator.toArray();
         const order = pairs.order && pairs.order.toArray();
         const distance = pairs.distance && pairs.distance.toArray();
         const flag = pairs.flag && pairs.flag.toArray();
         return {
-            bonds: getGraph(indexA, indexB, { key, order, distance, flag }, count),
+            bonds: getGraph(indexA, indexB, { key, operator, order, distance, flag }, count),
             maxDistance: p.maxDistance
         };
     }

+ 1 - 1
src/mol-model/structure/query/context.ts

@@ -155,6 +155,6 @@ class QueryContextBondInfo<U extends Unit = Unit> {
     }
 
     get length() {
-        return StructureElement.Location.distance(this.a, this. b);
+        return StructureElement.Location.distance(this.a, this.b);
     }
 }

+ 2 - 1
src/mol-model/structure/structure/properties.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -173,6 +173,7 @@ const unit = {
     multiChain: p(l => Unit.Traits.is(l.unit.traits, Unit.Trait.MultiChain)),
     object_primitive: p(l => l.unit.objectPrimitive),
     operator_name: p(l => l.unit.conformation.operator.name),
+    operator_key: p(l => l.unit.conformation.operator.key),
     model_index: p(l => l.unit.model.modelNum),
     model_label: p(l => l.unit.model.label),
     model_entry_id: p(l => l.unit.model.entryId),

+ 6 - 1
src/mol-model/structure/structure/unit/bonds/inter-compute.ts

@@ -20,6 +20,7 @@ import { InterUnitGraph } from '../../../../../mol-math/graph/inter-unit-graph';
 import { StructConn } from '../../../../../mol-model-formats/structure/property/bonds/struct_conn';
 import { equalEps } from '../../../../../mol-math/linear-algebra/3d/common';
 import { Model } from '../../../model';
+import { sortedCantorPairing } from '../../../../../mol-data/util';
 
 // avoiding namespace lookup improved performance in Chrome (Aug 2020)
 const v3distance = Vec3.distance;
@@ -71,6 +72,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
     const testDistanceSq = (bRadius + maxRadius) * (bRadius + maxRadius);
 
     builder.startUnitPair(unitA.id, unitB.id);
+    const opPairKey = sortedCantorPairing(unitA.conformation.operator.key, unitB.conformation.operator.key);
 
     for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
         const aI = atomsA[_aI];
@@ -80,7 +82,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
 
         if (!props.forceCompute && indexPairs) {
             const { maxDistance } = indexPairs;
-            const { offset, b, edgeProps: { order, distance, flag, key } } = indexPairs.bonds;
+            const { offset, b, edgeProps: { order, distance, flag, key, operator } } = indexPairs.bonds;
 
             const srcA = sourceIndex.value(aI);
             const aeI = getElementIdx(type_symbolA.value(aI));
@@ -90,6 +92,9 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
                 const _bI = SortedArray.indexOf(unitB.elements, bI) as StructureElement.UnitIndex;
                 if (_bI < 0) continue;
 
+                const op = operator[i];
+                if (op >= 0 && opPairKey !== op) continue;
+
                 const beI = getElementIdx(type_symbolA.value(bI));
 
                 const d = distance[i];

+ 7 - 1
src/mol-model/structure/structure/unit/bonds/intra-compute.ts

@@ -20,6 +20,7 @@ import { Vec3 } from '../../../../../mol-math/linear-algebra';
 import { ElementIndex } from '../../../model/indexing';
 import { equalEps } from '../../../../../mol-math/linear-algebra/3d/common';
 import { Model } from '../../../model/model';
+import { sortedCantorPairing } from '../../../../../mol-data/util';
 
 // avoiding namespace lookup improved performance in Chrome (Aug 2020)
 const v3distance = Vec3.distance;
@@ -55,7 +56,7 @@ function findIndexPairBonds(unit: Unit.Atomic) {
     const { type_symbol } = unit.model.atomicHierarchy.atoms;
     const atomCount = unit.elements.length;
     const { maxDistance } = indexPairs;
-    const { offset, b, edgeProps: { order, distance, flag, key } } = indexPairs.bonds;
+    const { offset, b, edgeProps: { order, distance, flag, key, operator } } = indexPairs.bonds;
 
     const { atomSourceIndex: sourceIndex } = unit.model.atomicHierarchy;
     const { invertedIndex } = Model.getInvertedAtomSourceIndex(unit.model);
@@ -66,6 +67,8 @@ function findIndexPairBonds(unit: Unit.Atomic) {
     const orders: number[] = [];
     const keys: number[] = [];
 
+    const opPairKey = sortedCantorPairing(unit.conformation.operator.key, unit.conformation.operator.key);
+
     for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
         const aI = atoms[_aI];
         const aeI = getElementIdx(type_symbol.value(aI));
@@ -80,6 +83,9 @@ function findIndexPairBonds(unit: Unit.Atomic) {
             const _bI = SortedArray.indexOf(unit.elements, bI) as StructureElement.UnitIndex;
             if (_bI < 0) continue;
 
+            const op = operator[i];
+            if (op >= 0 && opPairKey !== op) continue;
+
             const beI = getElementIdx(type_symbol.value(bI));
 
             const d = distance[i];

+ 1 - 0
src/mol-script/language/symbol-table/structure-query.ts

@@ -273,6 +273,7 @@ const atomProperty = {
 
         sourceIndex: atomProp(Type.Num, 'Index of the atom/element in the input file.'),
         operatorName: atomProp(Type.Str, 'Name of the symmetry operator applied to this element.'),
+        operatorKey: atomProp(Type.Num, 'Key of the symmetry operator applied to this element.'),
         modelIndex: atomProp(Type.Num, 'Index of the model in the input file.'),
         modelLabel: atomProp(Type.Str, 'Label/header of the model in the input file.')
     },

+ 1 - 0
src/mol-script/runtime/query/table.ts

@@ -299,6 +299,7 @@ const symbols = [
     D(MolScript.structureQuery.atomProperty.core.z, atomProp(StructureProperties.atom.z)),
     D(MolScript.structureQuery.atomProperty.core.sourceIndex, atomProp(StructureProperties.atom.sourceIndex)),
     D(MolScript.structureQuery.atomProperty.core.operatorName, atomProp(StructureProperties.unit.operator_name)),
+    D(MolScript.structureQuery.atomProperty.core.operatorKey, atomProp(StructureProperties.unit.operator_key)),
     D(MolScript.structureQuery.atomProperty.core.modelIndex, atomProp(StructureProperties.unit.model_index)),
     D(MolScript.structureQuery.atomProperty.core.modelLabel, atomProp(StructureProperties.unit.model_label)),
     D(MolScript.structureQuery.atomProperty.core.atomKey, (ctx, xs) => {

+ 4 - 1
src/mol-script/script/mol-script/symbols.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 Mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 import { UniqueArray } from '../../../mol-data/generic';
@@ -205,6 +206,7 @@ export const SymbolTable = [
             Alias(MolScript.structureQuery.atomProperty.core.z, 'atom.z'),
             Alias(MolScript.structureQuery.atomProperty.core.sourceIndex, 'atom.src-index'),
             Alias(MolScript.structureQuery.atomProperty.core.operatorName, 'atom.op-name'),
+            Alias(MolScript.structureQuery.atomProperty.core.operatorKey, 'atom.op-key'),
             Alias(MolScript.structureQuery.atomProperty.core.modelIndex, 'atom.model-index'),
             Alias(MolScript.structureQuery.atomProperty.core.modelLabel, 'atom.model-label'),
             Alias(MolScript.structureQuery.atomProperty.core.atomKey, 'atom.key'),
@@ -253,6 +255,7 @@ export const SymbolTable = [
             'Bond Properties',
             Alias(MolScript.structureQuery.bondProperty.order, 'bond.order'),
             Alias(MolScript.structureQuery.bondProperty.length, 'bond.length'),
+            Alias(MolScript.structureQuery.bondProperty.key, 'bond.key'),
             Alias(MolScript.structureQuery.bondProperty.atomA, 'bond.atom-a'),
             Alias(MolScript.structureQuery.bondProperty.atomB, 'bond.atom-b'),
             Macro(MSymbol('bond.is', Arguments.List(StructureQueryTypes.BondFlag), Type.Bool,