From 0c6670e83fe453d1f4af13d8b301c59df502db60 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Fri, 8 Jun 2018 10:04:30 +0200
Subject: [PATCH] Cache StructConn & ComponentBond

---
 .../structure/model/formats/mmcif/bonds.ts    | 45 +++++++++++--------
 src/mol-model/structure/model/model.ts        |  3 +-
 .../structure/unit/links/inter-compute.ts     |  2 +-
 .../structure/unit/links/intra-compute.ts     |  6 +--
 4 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/src/mol-model/structure/model/formats/mmcif/bonds.ts b/src/mol-model/structure/model/formats/mmcif/bonds.ts
index 85dca86ac..4eb625286 100644
--- a/src/mol-model/structure/model/formats/mmcif/bonds.ts
+++ b/src/mol-model/structure/model/formats/mmcif/bonds.ts
@@ -15,8 +15,8 @@ export interface StructConn {
     getAtomEntries(atomIndex: number): ReadonlyArray<StructConn.Entry>
 }
 
-export interface ComponentBondInfo {
-    entries: Map<string, ComponentBondInfo.Entry>
+export interface ComponentBond {
+    entries: Map<string, ComponentBond.Entry>
 }
 
 export namespace StructConn {
@@ -79,8 +79,6 @@ export namespace StructConn {
         }
     }
 
-
-
     export interface Entry {
         distance: number,
         order: number,
@@ -100,7 +98,10 @@ export namespace StructConn {
         | 'modres'
         | 'saltbr'
 
-    export function create(model: Model): StructConn | undefined {
+    export const PropName = '__StructConn__';
+    export function fromModel(model: Model): StructConn | undefined {
+        if (model.properties[PropName]) return model.properties[PropName];
+
         if (model.sourceData.kind !== 'mmCIF') return;
         const { struct_conn } = model.sourceData.data;
         if (!struct_conn._rowCount) return void 0;
@@ -187,21 +188,23 @@ export namespace StructConn {
             entries.push({ flags, order, distance: pdbx_dist_value.value(i), partners });
         }
 
-        return new StructConnImpl(entries);
+        const ret = new StructConnImpl(entries);
+        model.properties[PropName] = ret;
+        return ret;
     }
 }
 
-export class ComponentBondInfo implements ComponentBondInfo {
-    entries: Map<string, ComponentBondInfo.Entry> = new Map();
+export namespace ComponentBond {
+    export class ComponentBondImpl implements ComponentBond {
+        entries: Map<string, ComponentBond.Entry> = new Map();
 
-    newEntry(id: string) {
-        let e = new ComponentBondInfo.Entry(id);
-        this.entries.set(id, e);
-        return e;
+        addEntry(id: string) {
+            let e = new Entry(id);
+            this.entries.set(id, e);
+            return e;
+        }
     }
-}
 
-export namespace ComponentBondInfo {
     export class Entry implements Entry {
         map: Map<string, Map<string, { order: number, flags: number }>> = new Map();
 
@@ -225,16 +228,19 @@ export namespace ComponentBondInfo {
         }
     }
 
-    export function create(model: Model): ComponentBondInfo | undefined {
+    export const PropName = '__ComponentBond__';
+    export function fromModel(model: Model): ComponentBond | undefined {
+        if (model.properties[PropName]) return model.properties[PropName];
+
         if (model.sourceData.kind !== 'mmCIF') return
         const { chem_comp_bond } = model.sourceData.data;
         if (!chem_comp_bond._rowCount) return void 0;
 
-        let info = new ComponentBondInfo();
+        let compBond = new ComponentBondImpl();
 
         const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount: rowCount } = chem_comp_bond;
 
-        let entry = info.newEntry(comp_id.value(0)!);
+        let entry = compBond.addEntry(comp_id.value(0)!);
 
         for (let i = 0; i < rowCount; i++) {
 
@@ -245,7 +251,7 @@ export namespace ComponentBondInfo {
             const aromatic = pdbx_aromatic_flag.value(i) === 'Y';
 
             if (entry.id !== id) {
-                entry = info.newEntry(id);
+                entry = compBond.addEntry(id);
             }
 
             let flags: number = LinkType.Flag.Covalent;
@@ -263,6 +269,7 @@ export namespace ComponentBondInfo {
             entry.add(nameA, nameB, ord, flags);
         }
 
-        return info;
+        model.properties[PropName] = compBond;
+        return compBond;
     }
 }
\ No newline at end of file
diff --git a/src/mol-model/structure/model/model.ts b/src/mol-model/structure/model/model.ts
index da0037d65..a20eaf796 100644
--- a/src/mol-model/structure/model/model.ts
+++ b/src/mol-model/structure/model/model.ts
@@ -36,7 +36,8 @@ interface Model extends Readonly<{
     atomicHierarchy: AtomicHierarchy,
     atomicConformation: AtomicConformation,
 
-    properties: { secondaryStructure: SecondaryStructure },
+    /** Various parts of the code can "cache" custom properties here */
+    properties: { readonly secondaryStructure: SecondaryStructure } & { [customName: string]: any },
 
     coarseHierarchy: CoarseHierarchy,
     coarseConformation: CoarseConformation
diff --git a/src/mol-model/structure/structure/unit/links/inter-compute.ts b/src/mol-model/structure/structure/unit/links/inter-compute.ts
index abb607102..3eeb8ecc9 100644
--- a/src/mol-model/structure/structure/unit/links/inter-compute.ts
+++ b/src/mol-model/structure/structure/unit/links/inter-compute.ts
@@ -44,7 +44,7 @@ function findPairLinks(unitA: Unit.Atomic, unitB: Unit.Atomic, params: LinkCompu
     const { type_symbol: type_symbolA, label_alt_id: label_alt_idA } = unitA.model.atomicHierarchy.atoms;
     const { type_symbol: type_symbolB, label_alt_id: label_alt_idB } = unitB.model.atomicHierarchy.atoms;
     const { lookup3d } = unitB;
-    const structConn = unitA.model === unitB.model && unitA.model.sourceData.kind === 'mmCIF' ? StructConn.create(unitA.model) : void 0;
+    const structConn = unitA.model === unitB.model && unitA.model.sourceData.kind === 'mmCIF' ? StructConn.fromModel(unitA.model) : void 0;
 
     for (let _aI = 0; _aI < atomCount; _aI++) {
         const aI =  atomsA[_aI];
diff --git a/src/mol-model/structure/structure/unit/links/intra-compute.ts b/src/mol-model/structure/structure/unit/links/intra-compute.ts
index 43a67a8ac..28ee7cc7d 100644
--- a/src/mol-model/structure/structure/unit/links/intra-compute.ts
+++ b/src/mol-model/structure/structure/unit/links/intra-compute.ts
@@ -6,7 +6,7 @@
 
 import { LinkType } from '../../../model/types'
 import { IntraUnitLinks } from './data'
-import { StructConn, ComponentBondInfo } from '../../../model/formats/mmcif/bonds'
+import { StructConn, ComponentBond } from '../../../model/formats/mmcif/bonds'
 import Unit from '../../unit'
 import { IntAdjacencyGraph } from 'mol-math/graph';
 import { LinkComputationParameters, getElementIdx, MetalsSet, getElementThreshold, isHydrogen, getElementPairThreshold } from './common';
@@ -34,8 +34,8 @@ function _computeBonds(unit: Unit.Atomic, params: LinkComputationParameters): In
     const { label_comp_id } = unit.model.atomicHierarchy.residues;
     const query3d = unit.lookup3d;
 
-    const structConn = unit.model.sourceData.kind === 'mmCIF' ? StructConn.create(unit.model) : void 0;
-    const component = unit.model.sourceData.kind === 'mmCIF' ? ComponentBondInfo.create(unit.model) : void 0;
+    const structConn = unit.model.sourceData.kind === 'mmCIF' ? StructConn.fromModel(unit.model) : void 0;
+    const component = unit.model.sourceData.kind === 'mmCIF' ? ComponentBond.fromModel(unit.model) : void 0;
 
     const atomA: number[] = [];
     const atomB: number[] = [];
-- 
GitLab