Kaynağa Gözat

beter symmetry handling in index-pair bonds

Alexander Rose 5 yıl önce
ebeveyn
işleme
5a8fd6d518

+ 11 - 8
src/mol-model-formats/structure/cif-core.ts

@@ -118,22 +118,25 @@ async function getModels(db: CifCore_Database, format: CifCoreFormat, ctx: Runti
             const indexA: number[] = []
             const indexA: number[] = []
             const indexB: number[] = []
             const indexB: number[] = []
             const order: number[] = []
             const order: number[] = []
+            const symmetryA: string[] = []
+            const symmetryB: string[] = []
 
 
             const { atom_site_label_1, atom_site_label_2, valence, site_symmetry_1, site_symmetry_2 } = db.geom_bond
             const { atom_site_label_1, atom_site_label_2, valence, site_symmetry_1, site_symmetry_2 } = db.geom_bond
             for (let i = 0; i < bondCount; ++i) {
             for (let i = 0; i < bondCount; ++i) {
-                if (site_symmetry_1.value(i) === site_symmetry_2.value(i)) {
-                    indexA[i] = labelIndexMap[atom_site_label_1.value(i)]
-                    indexB[i] = labelIndexMap[atom_site_label_2.value(i)]
-                    // TODO derive from bond length if undefined
-                    order[i] = valence.isDefined ? valence.value(i) : 1
-                }
+                indexA[i] = labelIndexMap[atom_site_label_1.value(i)]
+                indexB[i] = labelIndexMap[atom_site_label_2.value(i)]
+                // TODO derive order from bond length if undefined
+                order[i] = valence.isDefined ? valence.value(i) : 1
+                symmetryA[i] = site_symmetry_1.value(i) || '1_555'
+                symmetryB[i] = site_symmetry_2.value(i) || '1_555'
             }
             }
 
 
-            // TODO support symmetry
             IndexPairBonds.Provider.set(models[0], IndexPairBonds.fromData({ pairs: {
             IndexPairBonds.Provider.set(models[0], IndexPairBonds.fromData({ pairs: {
                 indexA: Column.ofIntArray(indexA),
                 indexA: Column.ofIntArray(indexA),
                 indexB: Column.ofIntArray(indexB),
                 indexB: Column.ofIntArray(indexB),
-                order: Column.ofIntArray(order)
+                order: Column.ofIntArray(order),
+                symmetryA: Column.ofStringArray(symmetryA),
+                symmetryB: Column.ofStringArray(symmetryB)
             }, count: indexA.length }));
             }, count: indexA.length }));
         }
         }
     }
     }

+ 20 - 7
src/mol-model-formats/structure/property/bonds/index-pair.ts

@@ -9,17 +9,26 @@ import { IntAdjacencyGraph } from '../../../../mol-math/graph';
 import { Column } from '../../../../mol-data/db';
 import { Column } from '../../../../mol-data/db';
 import { FormatPropertyProvider } from '../../common/property';
 import { FormatPropertyProvider } from '../../common/property';
 
 
-export type IndexPairBonds = IntAdjacencyGraph<number, { readonly order: ArrayLike<number> }>
+export type IndexPairBondsProps = {
+    readonly order: ArrayLike<number>
+    readonly symmetryA: ArrayLike<string>
+    readonly symmetryB: ArrayLike<string>
+}
+export type IndexPairBonds = IntAdjacencyGraph<number, IndexPairBondsProps>
 
 
-function getGraph(indexA: ArrayLike<number>, indexB: ArrayLike<number>, _order: ArrayLike<number>, count: number): IndexPairBonds {
+function getGraph(indexA: ArrayLike<number>, indexB: ArrayLike<number>, props: Partial<IndexPairBondsProps>, count: number): IndexPairBonds {
     const builder = new IntAdjacencyGraph.EdgeBuilder(count, indexA, indexB);
     const builder = new IntAdjacencyGraph.EdgeBuilder(count, indexA, indexB);
     const order = new Int8Array(builder.slotCount);
     const order = new Int8Array(builder.slotCount);
+    const symmetryA = new Array(builder.slotCount);
+    const symmetryB = new Array(builder.slotCount);
     for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
     for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
         builder.addNextEdge();
         builder.addNextEdge();
-        builder.assignProperty(order, _order[i]);
+        builder.assignProperty(order, props.order ? props.order[i] : 1);
+        builder.assignProperty(symmetryA, props.symmetryA ? props.symmetryA[i] : '');
+        builder.assignProperty(symmetryB, props.symmetryB ? props.symmetryB[i] : '');
     }
     }
 
 
-    return builder.createGraph({ order });
+    return builder.createGraph({ order, symmetryA, symmetryB });
 }
 }
 
 
 export namespace IndexPairBonds {
 export namespace IndexPairBonds {
@@ -33,7 +42,9 @@ export namespace IndexPairBonds {
         pairs: {
         pairs: {
             indexA: Column<number>,
             indexA: Column<number>,
             indexB: Column<number>
             indexB: Column<number>
-            order: Column<number>
+            order?: Column<number>,
+            symmetryA?: Column<string>,
+            symmetryB?: Column<string>,
         },
         },
         count: number
         count: number
     }
     }
@@ -42,7 +53,9 @@ export namespace IndexPairBonds {
         const { pairs, count } = data
         const { pairs, count } = data
         const indexA = pairs.indexA.toArray()
         const indexA = pairs.indexA.toArray()
         const indexB = pairs.indexB.toArray()
         const indexB = pairs.indexB.toArray()
-        const order = pairs.order.toArray()
-        return getGraph(indexA, indexB, order, count);
+        const order = pairs.order && pairs.order.toArray()
+        const symmetryA = pairs.symmetryA && pairs.symmetryA.toArray()
+        const symmetryB = pairs.symmetryB && pairs.symmetryB.toArray()
+        return getGraph(indexA, indexB, { order, symmetryA, symmetryB }, count);
     }
     }
 }
 }

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

@@ -59,6 +59,8 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
     const testDistanceSq = (bRadius + MAX_RADIUS) * (bRadius + MAX_RADIUS);
     const testDistanceSq = (bRadius + MAX_RADIUS) * (bRadius + MAX_RADIUS);
 
 
     builder.startUnitPair(unitA, unitB)
     builder.startUnitPair(unitA, unitB)
+    const symmUnitA = unitA.conformation.operator.name
+    const symmUnitB = unitB.conformation.operator.name
 
 
     for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
     for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
         const aI = atomsA[_aI];
         const aI = atomsA[_aI];
@@ -67,10 +69,14 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
         if (Vec3.squaredDistance(imageA, bCenter) > testDistanceSq) continue;
         if (Vec3.squaredDistance(imageA, bCenter) > testDistanceSq) continue;
 
 
         if (!props.forceCompute && indexPairs) {
         if (!props.forceCompute && indexPairs) {
+            const { order, symmetryA, symmetryB } = indexPairs.edgeProps
             for (let i = indexPairs.offset[aI], il = indexPairs.offset[aI + 1]; i < il; ++i) {
             for (let i = indexPairs.offset[aI], il = indexPairs.offset[aI + 1]; i < il; ++i) {
                 const _bI = SortedArray.indexOf(unitA.elements, indexPairs.b[i]) as StructureElement.UnitIndex;
                 const _bI = SortedArray.indexOf(unitA.elements, indexPairs.b[i]) as StructureElement.UnitIndex;
                 if (_bI < 0) continue;
                 if (_bI < 0) continue;
-                builder.add(_aI, _bI, { order: indexPairs.edgeProps.order[i], flag: BondType.Flag.Covalent });
+                if (symmetryA[i] === symmetryB[i]) continue;
+                if (symmUnitA === symmetryA[i] && symmUnitB === symmetryB[i]) {
+                    builder.add(_aI, _bI, { order: order[i], flag: BondType.Flag.Covalent });
+                }
             }
             }
             continue // assume `indexPairs` supplies all bonds
             continue // assume `indexPairs` supplies all bonds
         }
         }

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

@@ -60,12 +60,14 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni
         const aI =  atoms[_aI];
         const aI =  atoms[_aI];
 
 
         if (!props.forceCompute && indexPairs) {
         if (!props.forceCompute && indexPairs) {
+            const { edgeProps } = indexPairs
             for (let i = indexPairs.offset[aI], il = indexPairs.offset[aI + 1]; i < il; ++i) {
             for (let i = indexPairs.offset[aI], il = indexPairs.offset[aI + 1]; i < il; ++i) {
                 const _bI = SortedArray.indexOf(unit.elements, indexPairs.b[i]) as StructureElement.UnitIndex;
                 const _bI = SortedArray.indexOf(unit.elements, indexPairs.b[i]) as StructureElement.UnitIndex;
                 if (_bI < 0) continue;
                 if (_bI < 0) continue;
+                if (edgeProps.symmetryA[i] !== edgeProps.symmetryB[i]) continue;
                 atomA[atomA.length] = _aI;
                 atomA[atomA.length] = _aI;
                 atomB[atomB.length] = _bI;
                 atomB[atomB.length] = _bI;
-                order[order.length] = indexPairs.edgeProps.order[i];
+                order[order.length] = edgeProps.order[i];
                 flags[flags.length] = BondType.Flag.Covalent;
                 flags[flags.length] = BondType.Flag.Covalent;
             }
             }
             continue // assume `indexPairs` supplies all bonds
             continue // assume `indexPairs` supplies all bonds