Sfoglia il codice sorgente

Merge branch 'master' into repr-getAllLoci

Alexander Rose 2 anni fa
parent
commit
8a18f25b5d

+ 1 - 0
CHANGELOG.md

@@ -10,6 +10,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Add ``includeResidueTest`` option to ``alignAndSuperposeWithSIFTSMapping``
 - Add ``parentDisplay`` param for interactions representation.
 - Add support for getting multiple loci from a representation (``.getAllLoci()``)
+- Add ``key`` property to intra- and inter-bonds for referencing source data
 
 ## [v3.16.0] - 2022-08-25
 

+ 9 - 8
src/mol-model-formats/structure/property/bonds/chem_comp.ts

@@ -65,7 +65,7 @@ export namespace ComponentBond {
             return e;
         }
 
-        const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount } = data;
+        const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount, pdbx_ordinal } = data;
 
         let entry = addEntry(comp_id.value(0)!);
         for (let i = 0; i < _rowCount; i++) {
@@ -74,6 +74,7 @@ export namespace ComponentBond {
             const nameB = atom_id_2.value(i)!;
             const order = value_order.value(i)!;
             const aromatic = pdbx_aromatic_flag.value(i) === 'y';
+            const key = pdbx_ordinal.value(i);
 
             if (entry.id !== id) {
                 entry = addEntry(id);
@@ -89,29 +90,29 @@ export namespace ComponentBond {
                 case 'quad': ord = 4; break;
             }
 
-            entry.add(nameA, nameB, ord, flags);
+            entry.add(nameA, nameB, ord, flags, key);
         }
 
         return entries;
     }
 
     export class Entry {
-        readonly map: Map<string, Map<string, { order: number, flags: number }>> = new Map();
+        readonly map: Map<string, Map<string, { order: number, flags: number, key: number }>> = new Map();
 
-        add(a: string, b: string, order: number, flags: number, swap = true) {
+        add(a: string, b: string, order: number, flags: number, key: number, swap = true) {
             const e = this.map.get(a);
             if (e !== void 0) {
                 const f = e.get(b);
                 if (f === void 0) {
-                    e.set(b, { order, flags });
+                    e.set(b, { order, flags, key });
                 }
             } else {
-                const map = new Map<string, { order: number, flags: number }>();
-                map.set(b, { order, flags });
+                const map = new Map<string, { order: number, flags: number, key: number }>();
+                map.set(b, { order, flags, key });
                 this.map.set(a, map);
             }
 
-            if (swap) this.add(b, a, order, flags, false);
+            if (swap) this.add(b, a, order, flags, key, false);
         }
 
         constructor(public readonly id: string) { }

+ 3 - 1
src/mol-model/structure/query/context.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 { Structure, StructureElement, Unit } from '../structure';
@@ -113,6 +114,7 @@ class QueryContextBondInfo<U extends Unit = Unit> {
     bIndex: StructureElement.UnitIndex = 0 as StructureElement.UnitIndex;
     type: BondType = BondType.Flag.None;
     order: number = 0;
+    key: number = -1;
 
     private testFn: QueryPredicate = defaultBondTest;
 

+ 5 - 2
src/mol-model/structure/query/queries/filters.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 { SetUtils } from '../../../../mol-util/set';
@@ -248,7 +249,7 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
 
         const inputUnit = input.unitMap.get(unit.id) as Unit.Atomic;
 
-        const { offset, b, edgeProps: { flags, order } } = inputUnit.bonds;
+        const { offset, b, edgeProps: { flags, order, key } } = inputUnit.bonds;
         const bondedUnits = interBonds.getConnectedUnits(unit.id);
         const buCount = bondedUnits.length;
 
@@ -273,6 +274,7 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
                 atomicBond.bIndex = b[l] as StructureElement.UnitIndex;
                 atomicBond.type = flags[l];
                 atomicBond.order = order[l];
+                atomicBond.key = key[l];
                 if (atomicBond.test(queryCtx, true)) return true;
             }
 
@@ -295,6 +297,7 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
                     atomicBond.bIndex = bond.indexB;
                     atomicBond.type = bond.props.flag;
                     atomicBond.order = bond.props.order;
+                    atomicBond.key = bond.props.key;
                     if (atomicBond.test(queryCtx, true)) return true;
                 }
             }

+ 4 - 2
src/mol-model/structure/query/queries/generators.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017-2019 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>
@@ -322,7 +322,7 @@ export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery {
         for (const unit of structure.units) {
             if (unit.kind !== Unit.Kind.Atomic) continue;
 
-            const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order } } = unit.bonds;
+            const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order, key } } = unit.bonds;
             atomicBond.a.unit = unit;
             atomicBond.b.unit = unit;
             for (let i = 0 as StructureElement.UnitIndex, _i = unit.elements.length; i < _i; i++) {
@@ -335,6 +335,7 @@ export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery {
                     atomicBond.b.element = unit.elements[intraBondB[lI]];
                     atomicBond.type = flags[lI];
                     atomicBond.order = order[lI];
+                    atomicBond.key = key[lI];
                     // No need to "swap test" because each bond direction will be visited eventually.
                     if (atomicBond.test(ctx, false)) {
                         const b = structure.subsetBuilder(false);
@@ -358,6 +359,7 @@ export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery {
             atomicBond.bIndex = bond.indexB;
             atomicBond.order = bond.props.order;
             atomicBond.type = bond.props.flag;
+            atomicBond.key = bond.props.key;
 
             // No need to "swap test" because each bond direction will be visited eventually.
             if (atomicBond.test(ctx, false)) {

+ 5 - 2
src/mol-model/structure/query/queries/modifiers.ts

@@ -1,7 +1,8 @@
 /**
- * Copyright (c) 2017-2020 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 { Segmentation, SortedArray } from '../../../../mol-data/int';
@@ -370,7 +371,7 @@ function expandConnected(ctx: QueryContext, structure: Structure) {
         }
 
         const inputUnitA = inputStructure.unitMap.get(unit.id) as Unit.Atomic;
-        const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order } } = inputUnitA.bonds;
+        const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order, key } } = inputUnitA.bonds;
 
         atomicBond.setStructure(inputStructure);
 
@@ -397,6 +398,7 @@ function expandConnected(ctx: QueryContext, structure: Structure) {
                 atomicBond.b.element = bElement;
                 atomicBond.type = flags[lI];
                 atomicBond.order = order[lI];
+                atomicBond.key = key[lI];
 
                 if (atomicBond.test(ctx, true)) {
                     builder.addToUnit(unit.id, bElement);
@@ -427,6 +429,7 @@ function expandConnected(ctx: QueryContext, structure: Structure) {
                     atomicBond.b.element = bElement;
                     atomicBond.type = bond.props.flag;
                     atomicBond.order = bond.props.order;
+                    atomicBond.key = bond.props.key;
 
                     if (atomicBond.test(ctx, true)) {
                         builder.addToUnit(bondedUnit.unitB, bElement);

+ 3 - 2
src/mol-model/structure/structure/unit/bonds/data.ts

@@ -15,16 +15,17 @@ import { InterUnitGraph } from '../../../../../mol-math/graph/inter-unit-graph';
 type IntraUnitBonds = IntAdjacencyGraph<StructureElement.UnitIndex, {
     readonly order: ArrayLike<number>,
     readonly flags: ArrayLike<BondType.Flag>
+    readonly key: ArrayLike<number>,
 }, {
     /** can remap even with dynamicBonds on, e.g., for water molecules */
     readonly canRemap?: boolean
 }>
 
 namespace IntraUnitBonds {
-    export const Empty: IntraUnitBonds = IntAdjacencyGraph.create([], [], [], 0, { flags: [], order: [] });
+    export const Empty: IntraUnitBonds = IntAdjacencyGraph.create([], [], [], 0, { flags: [], order: [], key: [] });
 }
 
-type InterUnitEdgeProps = { readonly order: number, readonly flag: BondType.Flag }
+type InterUnitEdgeProps = { readonly order: number, readonly flag: BondType.Flag, readonly key: number }
 
 class InterUnitBonds extends InterUnitGraph<number, StructureElement.UnitIndex, InterUnitEdgeProps> {
     /** Get inter-unit bond given a bond-location */

+ 5 - 4
src/mol-model/structure/structure/unit/bonds/inter-compute.ts

@@ -80,7 +80,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 } } = indexPairs.bonds;
+            const { offset, b, edgeProps: { order, distance, flag, key } } = indexPairs.bonds;
 
             const srcA = sourceIndex.value(aI);
             const aeI = getElementIdx(type_symbolA.value(aI));
@@ -113,7 +113,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
                 }
 
                 if (add) {
-                    builder.add(_aI, _bI, { order: order[i], flag: flag[i] });
+                    builder.add(_aI, _bI, { order: order[i], flag: flag[i], key: key[i] });
                 }
             }
             continue; // assume `indexPairs` supplies all bonds
@@ -131,7 +131,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
                 // check if the bond is within MAX_RADIUS for this pair of units
                 if (getDistance(unitA, aI, unitB, p.atomIndex) > maxRadius) continue;
 
-                builder.add(_aI, _bI, { order: se.order, flag: se.flags });
+                builder.add(_aI, _bI, { order: se.order, flag: se.flags, key: se.rowIndex });
                 added = true;
             }
             // assume, for an atom, that if any inter unit bond is given
@@ -187,7 +187,8 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
                 const compIdB = label_comp_idB.value(residueIndexB[bI]);
                 builder.add(_aI, _bI, {
                     order: getInterBondOrderFromTable(compIdA, compIdB, atomIdA, atomIdB),
-                    flag: (isMetal ? BondType.Flag.MetallicCoordination : BondType.Flag.Covalent) | BondType.Flag.Computed
+                    flag: (isMetal ? BondType.Flag.MetallicCoordination : BondType.Flag.Covalent) | BondType.Flag.Computed,
+                    key: -1
                 });
             }
         }

+ 14 - 6
src/mol-model/structure/structure/unit/bonds/intra-compute.ts

@@ -24,17 +24,19 @@ import { Model } from '../../../model/model';
 // avoiding namespace lookup improved performance in Chrome (Aug 2020)
 const v3distance = Vec3.distance;
 
-function getGraph(atomA: StructureElement.UnitIndex[], atomB: StructureElement.UnitIndex[], _order: number[], _flags: number[], atomCount: number, canRemap: boolean): IntraUnitBonds {
+function getGraph(atomA: StructureElement.UnitIndex[], atomB: StructureElement.UnitIndex[], _order: number[], _flags: number[], _key: number[], atomCount: number, canRemap: boolean): IntraUnitBonds {
     const builder = new IntAdjacencyGraph.EdgeBuilder(atomCount, atomA, atomB);
     const flags = new Uint16Array(builder.slotCount);
     const order = new Int8Array(builder.slotCount);
+    const key = new Uint32Array(builder.slotCount);
     for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
         builder.addNextEdge();
         builder.assignProperty(flags, _flags[i]);
         builder.assignProperty(order, _order[i]);
+        builder.assignProperty(key, _key[i]);
     }
 
-    return builder.createGraph({ flags, order }, { canRemap });
+    return builder.createGraph({ flags, order, key }, { canRemap });
 }
 
 const tmpDistVecA = Vec3();
@@ -53,7 +55,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 } } = indexPairs.bonds;
+    const { offset, b, edgeProps: { order, distance, flag, key } } = indexPairs.bonds;
 
     const { atomSourceIndex: sourceIndex } = unit.model.atomicHierarchy;
     const { invertedIndex } = Model.getInvertedAtomSourceIndex(unit.model);
@@ -62,6 +64,7 @@ function findIndexPairBonds(unit: Unit.Atomic) {
     const atomB: StructureElement.UnitIndex[] = [];
     const flags: number[] = [];
     const orders: number[] = [];
+    const keys: number[] = [];
 
     for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
         const aI = atoms[_aI];
@@ -104,11 +107,12 @@ function findIndexPairBonds(unit: Unit.Atomic) {
                 atomB[atomB.length] = _bI;
                 orders[orders.length] = order[i];
                 flags[flags.length] = flag[i];
+                keys[keys.length] = key[i];
             }
         }
     }
 
-    return getGraph(atomA, atomB, orders, flags, atomCount, false);
+    return getGraph(atomA, atomB, orders, flags, keys, atomCount, false);
 }
 
 function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBonds {
@@ -132,9 +136,10 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
     const atomB: StructureElement.UnitIndex[] = [];
     const flags: number[] = [];
     const order: number[] = [];
+    const key: number[] = [];
 
     let lastResidue = -1;
-    let componentMap: Map<string, Map<string, { flags: number, order: number }>> | undefined = void 0;
+    let componentMap: Map<string, Map<string, { flags: number, order: number, key: number }>> | undefined = void 0;
 
     let isWatery = true, isDictionaryBased = true, isSequenced = true;
 
@@ -162,6 +167,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
                 atomB[atomB.length] = _bI;
                 flags[flags.length] = se.flags;
                 order[order.length] = se.order;
+                key[key.length] = se.rowIndex;
 
                 if (!hasStructConn) structConnAdded.clear();
                 hasStructConn = true;
@@ -230,6 +236,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
                         flag |= BondType.Flag.MetallicCoordination;
                     }
                     flags[flags.length] = flag;
+                    key[key.length] = e.key;
                 }
                 continue;
             }
@@ -243,6 +250,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
                 atomB[atomB.length] = _bI;
                 order[order.length] = getIntraBondOrderFromTable(compId, atomIdA, label_atom_id.value(bI));
                 flags[flags.length] = (isMetal ? BondType.Flag.MetallicCoordination : BondType.Flag.Covalent) | BondType.Flag.Computed;
+                key[key.length] = -1;
 
                 const seqIdB = label_seq_id.value(rbI);
 
@@ -253,7 +261,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
     }
 
     const canRemap = isWatery || (isDictionaryBased && isSequenced);
-    return getGraph(atomA, atomB, order, flags, atomCount, canRemap);
+    return getGraph(atomA, atomB, order, flags, key, atomCount, canRemap);
 }
 
 function computeIntraUnitBonds(unit: Unit.Atomic, props?: Partial<BondComputationProps>) {

+ 3 - 2
src/mol-script/language/symbol-table/structure-query.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2019 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>
@@ -333,6 +333,7 @@ const bondProperty = {
 
     flags: bondProp(Types.BondFlags),
     order: bondProp(Type.Num),
+    key: bondProp(Type.Num),
     length: bondProp(Type.Num),
     atomA: bondProp(Types.ElementReference),
     atomB: bondProp(Types.ElementReference)
@@ -356,5 +357,5 @@ export const structureQuery = {
     combinator,
     atomSet,
     atomProperty,
-    bondProperty: bondProperty
+    bondProperty
 };

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

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2019 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>
@@ -356,6 +356,7 @@ const symbols = [
     // ============= BOND PROPERTIES ================
     D(MolScript.structureQuery.bondProperty.order, (ctx, xs) => ctx.atomicBond.order),
     D(MolScript.structureQuery.bondProperty.flags, (ctx, xs) => ctx.atomicBond.type),
+    D(MolScript.structureQuery.bondProperty.key, (ctx, xs) => ctx.atomicBond.key),
     D(MolScript.structureQuery.bondProperty.atomA, (ctx, xs) => ctx.atomicBond.a),
     D(MolScript.structureQuery.bondProperty.atomB, (ctx, xs) => ctx.atomicBond.b),
     D(MolScript.structureQuery.bondProperty.length, (ctx, xs) => ctx.atomicBond.length),