Kaynağa Gözat

wip, carb mark/getLoci

Alexander Rose 6 yıl önce
ebeveyn
işleme
93a2512793

+ 46 - 1
src/mol-model/structure/structure/carbohydrates/compute.ts

@@ -348,6 +348,26 @@ function buildLookups (elements: CarbohydrateElement[], links: CarbohydrateLink[
         return linkMap.get(linkKey(unitA, anomericCarbonA, unitB, anomericCarbonB))
     }
 
+    // links lookup
+
+    function linksKey(unit: Unit, anomericCarbon: ElementIndex) {
+        return `${unit.id}|${anomericCarbon}`
+    }
+
+    const linksMap = new Map<string, number[]>()
+    for (let i = 0, il = links.length; i < il; ++i) {
+        const l = links[i]
+        const { unit, anomericCarbon } = elements[l.carbohydrateIndexA]
+        const k = linksKey(unit, anomericCarbon)
+        const e = linksMap.get(k)
+        if (e === undefined) linksMap.set(k, [i])
+        else e.push(i)
+    }
+
+    function getLinkIndices(unit: Unit, anomericCarbon: ElementIndex): ReadonlyArray<number> {
+        return linksMap.get(linksKey(unit, anomericCarbon)) || []
+    }
+
     // terminal link lookup
 
     function terminalLinkKey(unitA: Unit, elementA: ElementIndex, unitB: Unit, elementB: ElementIndex) {
@@ -369,6 +389,31 @@ function buildLookups (elements: CarbohydrateElement[], links: CarbohydrateLink[
         return terminalLinkMap.get(terminalLinkKey(unitA, elementA, unitB, elementB))
     }
 
+    // terminal links lookup
+
+    function terminalLinksKey(unit: Unit, element: ElementIndex) {
+        return `${unit.id}|${element}`
+    }
+
+    const terminalLinksMap = new Map<string, number[]>()
+    for (let i = 0, il = terminalLinks.length; i < il; ++i) {
+        const { fromCarbohydrate, carbohydrateIndex, elementUnit, elementIndex } = terminalLinks[i]
+        const { unit, anomericCarbon } = elements[carbohydrateIndex]
+        let k: string
+        if (fromCarbohydrate) {
+            k = terminalLinksKey(unit, anomericCarbon)
+        } else{
+            k = terminalLinksKey(elementUnit, elementUnit.elements[elementIndex])
+        }
+        const e = terminalLinksMap.get(k)
+        if (e === undefined) terminalLinksMap.set(k, [i])
+        else e.push(i)
+    }
+
+    function getTerminalLinkIndices(unit: Unit, element: ElementIndex): ReadonlyArray<number> {
+        return terminalLinksMap.get(terminalLinksKey(unit, element)) || []
+    }
+
     // anomeric carbon lookup
 
     function anomericCarbonKey(unit: Unit, residueIndex: ResidueIndex) {
@@ -386,5 +431,5 @@ function buildLookups (elements: CarbohydrateElement[], links: CarbohydrateLink[
         return anomericCarbonMap.get(anomericCarbonKey(unit, residueIndex))
     }
 
-    return { getElementIndex, getLinkIndex, getTerminalLinkIndex, getAnomericCarbon }
+    return { getElementIndex, getLinkIndex, getLinkIndices, getTerminalLinkIndex, getTerminalLinkIndices, getAnomericCarbon }
 }

+ 2 - 0
src/mol-model/structure/structure/carbohydrates/data.ts

@@ -46,6 +46,8 @@ export interface Carbohydrates {
     partialElements: ReadonlyArray<PartialCarbohydrateElement>
     getElementIndex: (unit: Unit, anomericCarbon: ElementIndex) => number | undefined
     getLinkIndex: (unitA: Unit, anomericCarbonA: ElementIndex, unitB: Unit, anomericCarbonB: ElementIndex) => number | undefined
+    getLinkIndices: (unit: Unit, anomericCarbon: ElementIndex) => ReadonlyArray<number>
     getTerminalLinkIndex: (unitA: Unit, elementA: ElementIndex, unitB: Unit, elementB: ElementIndex) => number | undefined
+    getTerminalLinkIndices: (unit: Unit, element: ElementIndex) => ReadonlyArray<number>
     getAnomericCarbon: (unit: Unit, residueIndex: ResidueIndex) => ElementIndex | undefined
 }

+ 1 - 3
src/mol-model/structure/structure/unit/links/data.ts

@@ -51,9 +51,7 @@ class InterUnitBonds {
 
     /** Indices into this.bonds */
     getBondIndices(index: StructureElement.UnitIndex, unit: Unit): ReadonlyArray<number> {
-        const elementKey = InterUnitBonds.getElementKey(index, unit)
-        const indices = this.elementKeyIndex.get(elementKey)
-        return indices !== undefined ? indices : []
+        return this.elementKeyIndex.get(InterUnitBonds.getElementKey(index, unit)) || []
     }
 
     constructor(private map: Map<number, InterUnitBonds.UnitPairBonds[]>) {

+ 18 - 2
src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts

@@ -117,16 +117,32 @@ function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
 }
 
 function markLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
-    const { getLinkIndex } = structure.carbohydrates
-
     let changed = false
     if (Link.isLoci(loci)) {
+        if (loci.structure !== structure) return false
+        const { getLinkIndex } = structure.carbohydrates
         for (const l of loci.links) {
             const idx = getLinkIndex(l.aUnit, l.aUnit.elements[l.aIndex], l.bUnit, l.bUnit.elements[l.bIndex])
             if (idx !== undefined) {
                 if (apply(Interval.ofSingleton(idx))) changed = true
             }
         }
+    } else if (StructureElement.isLoci(loci)) {
+        if (loci.structure !== structure) return false
+        // TODO mark link only when both of the link elements are in a StructureElement.Loci
+        const { getElementIndex, getLinkIndices, elements } = structure.carbohydrates
+        for (const e of loci.elements) {
+            OrderedSet.forEach(e.indices, v => {
+                const carbI = getElementIndex(e.unit, e.unit.elements[v])
+                if (carbI !== undefined) {
+                    const carb = elements[carbI]
+                    const indices = getLinkIndices(carb.unit, carb.anomericCarbon)
+                    for (let i = 0, il = indices.length; i < il; ++i) {
+                        if (apply(Interval.ofSingleton(indices[i]))) changed = true
+                    }
+                }
+            })
+        }
     }
     return changed
 }

+ 17 - 1
src/mol-repr/structure/visual/carbohydrate-terminal-link-cylinder.ts

@@ -128,7 +128,7 @@ function getTerminalLinkLoci(pickingId: PickingId, structure: Structure, id: num
     return EmptyLoci
 }
 
-// TODO mark link when both (or one) of the link elements are in a StructureElement.Loci
+// TODO mark link when both of the link elements are in a StructureElement.Loci
 function markTerminalLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
     const { getTerminalLinkIndex } = structure.carbohydrates
 
@@ -140,6 +140,22 @@ function markTerminalLink(loci: Loci, structure: Structure, apply: (interval: In
                 if (apply(Interval.ofSingleton(idx))) changed = true
             }
         }
+    } else if (StructureElement.isLoci(loci)) {
+        if (loci.structure !== structure) return false
+        // TODO mark link only when both of the link elements are in a StructureElement.Loci
+        const { getElementIndex, getTerminalLinkIndices, elements } = structure.carbohydrates
+        for (const e of loci.elements) {
+            OrderedSet.forEach(e.indices, v => {
+                const carbI = getElementIndex(e.unit, e.unit.elements[v])
+                if (carbI !== undefined) {
+                    const carb = elements[carbI]
+                    const indices = getTerminalLinkIndices(carb.unit, carb.anomericCarbon)
+                    for (let i = 0, il = indices.length; i < il; ++i) {
+                        if (apply(Interval.ofSingleton(indices[i]))) changed = true
+                    }
+                }
+            })
+        }
     }
     return changed
 }

+ 4 - 1
src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts

@@ -95,7 +95,10 @@ function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
     if (id === objectId) {
         const pair = structure.crossLinkRestraints.pairs[groupId]
         if (pair) {
-            return Link.Loci(structure, [ Link.Location(pair.unitA, pair.indexA, pair.unitB, pair.indexB) ])
+            return Link.Loci(structure, [
+                Link.Location(pair.unitA, pair.indexA, pair.unitB, pair.indexB),
+                Link.Location(pair.unitB, pair.indexB, pair.unitA, pair.indexA)
+            ])
         }
     }
     return EmptyLoci

+ 1 - 0
src/mol-repr/structure/visual/inter-unit-link-cylinder.ts

@@ -107,6 +107,7 @@ function markLink(loci: Loci, structure: Structure, apply: (interval: Interval)
         }
     } else if (StructureElement.isLoci(loci)) {
         if (loci.structure !== structure) return false
+        // TODO mark link only when both of the link elements are in a StructureElement.Loci
         for (const e of loci.elements) {
             OrderedSet.forEach(e.indices, v => {
                 const indices = structure.links.getBondIndices(v, e.unit)

+ 4 - 2
src/mol-repr/structure/visual/intra-unit-link-cylinder.ts

@@ -138,10 +138,12 @@ function markLink(loci: Loci, structureGroup: StructureGroup, apply: (interval:
         for (const e of loci.elements) {
             const unitIdx = group.unitIndexMap.get(e.unit.id)
             if (unitIdx !== undefined) {
-                const { offset } = unit.links
+                const { offset, b } = unit.links
                 OrderedSet.forEach(e.indices, v => {
                     for (let t = offset[v], _t = offset[v + 1]; t < _t; t++) {
-                        if (apply(Interval.ofSingleton(unitIdx * groupCount + t))) changed = true
+                        if (OrderedSet.has(e.indices, b[t])) {
+                            if (apply(Interval.ofSingleton(unitIdx * groupCount + t))) changed = true
+                        }
                     }
                 })
             }