From ea7b1ba9fa1aca2f5b31ae3a00b26df363028c74 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Fri, 3 Nov 2017 09:56:41 +0100
Subject: [PATCH] segmentation tweaks

---
 .../collections/integer/impl/segmentation.ts  | 28 ++++++++-----------
 .../collections/integer/segmentation.ts       |  3 +-
 src/mol-data/structure/query/generators.ts    |  4 +--
 src/perf-tests/structure.ts                   |  4 +--
 4 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/src/mol-base/collections/integer/impl/segmentation.ts b/src/mol-base/collections/integer/impl/segmentation.ts
index 567eee22d..357252a63 100644
--- a/src/mol-base/collections/integer/impl/segmentation.ts
+++ b/src/mol-base/collections/integer/impl/segmentation.ts
@@ -48,7 +48,6 @@ export class SegmentIterator implements Iterator<Segs.Segment> {
     private segmentMax = 0;
     private setRange = Interval.Empty;
     private value: Segs.Segment = { index: 0, start: 0, end: 0 };
-    private last: number = 0;
 
     hasNext: boolean = false;
 
@@ -65,18 +64,13 @@ export class SegmentIterator implements Iterator<Segs.Segment> {
         return this.value;
     }
 
-    private getSegmentIndex(value: number) {
-        if (value >= this.last) return -1;
-        return SortedArray.findPredecessorIndex(this.segments, value + 1) - 1;
-    }
-
     private updateValue() {
         const segmentEnd = this.segments[this.segmentMin + 1];
+        // TODO: add optimized version for interval and array?
         const setEnd = OrderedSet.findPredecessorIndexInInterval(this.set, segmentEnd, this.setRange);
         this.value.start = Interval.start(this.setRange);
         this.value.end = setEnd;
-        const rEnd = Interval.end(this.setRange);
-        this.setRange = Interval.ofBounds(setEnd, rEnd);
+        this.setRange = Interval.ofBounds(setEnd, Interval.end(this.setRange));
         return setEnd > this.value.start;
     }
 
@@ -87,16 +81,18 @@ export class SegmentIterator implements Iterator<Segs.Segment> {
             return;
         }
 
-        const min = OrderedSet.getAt(this.set, sMin);
-        const max = OrderedSet.getAt(this.set, sMax);
-        this.segmentMin = this.getSegmentIndex(min);
-        this.segmentMax = this.getSegmentIndex(max);
+        this.segmentMin = this.segmentMap[OrderedSet.getAt(this.set, sMin)];
+        this.segmentMax = this.segmentMap[OrderedSet.getAt(this.set, sMax)];
 
-        this.hasNext = this.segmentMax >= this.segmentMin && Interval.size(this.setRange) > 0;
+        this.hasNext = this.segmentMax >= this.segmentMin;
+    }
+
+    setSegment(segment: Segs.Segment) {
+        this.setRange = Interval.ofBounds(segment.start, segment.end);
+        this.updateSegmentRange();
     }
 
-    constructor(private segments: SortedArray, private set: OrderedSet, inputRange: Interval) {
-        this.last = SortedArray.max(segments);
+    constructor(private segments: SortedArray, private segmentMap: Int32Array, private set: OrderedSet, inputRange: Interval) {
         this.setRange = inputRange;
         this.updateSegmentRange();
     }
@@ -104,5 +100,5 @@ export class SegmentIterator implements Iterator<Segs.Segment> {
 
 export function segments(segs: Segmentation, set: OrderedSet, segment?: Segs.Segment) {
     const int = typeof segment !== 'undefined' ? Interval.ofBounds(segment.start, segment.end) : Interval.ofBounds(0, OrderedSet.size(set));
-    return new SegmentIterator(segs.segments, set, int);
+    return new SegmentIterator(segs.segments, segs.segmentMap, set, int);
 }
\ No newline at end of file
diff --git a/src/mol-base/collections/integer/segmentation.ts b/src/mol-base/collections/integer/segmentation.ts
index b986fe401..3416c530b 100644
--- a/src/mol-base/collections/integer/segmentation.ts
+++ b/src/mol-base/collections/integer/segmentation.ts
@@ -4,7 +4,6 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import Iterator from '../iterator'
 import Interval from './interval'
 import OrderedSet from './ordered-set'
 import * as Impl from './impl/segmentation'
@@ -20,7 +19,7 @@ namespace Segmentation {
     export const projectValue: (segs: Segmentation, set: OrderedSet, value: number) => Interval = Impl.projectValue as any;
 
     // Segment iterator that mutates a single segment object to mark all the segments.
-    export const transientSegments: (segs: Segmentation, set: OrderedSet, segment?: Segment) => Iterator<Segment> = Impl.segments as any;
+    export const transientSegments: (segs: Segmentation, set: OrderedSet, segment?: Segment) => Impl.SegmentIterator = Impl.segments as any;
 }
 
 interface Segmentation {
diff --git a/src/mol-data/structure/query/generators.ts b/src/mol-data/structure/query/generators.ts
index eb6cb5403..9a30d0a3d 100644
--- a/src/mol-data/structure/query/generators.ts
+++ b/src/mol-data/structure/query/generators.ts
@@ -74,14 +74,14 @@ function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: A
 
             builder.beginUnit();
             const chainsIt = Segmentation.transientSegments(unit.hierarchy.chainSegments, set);
-            const residues = unit.hierarchy.residueSegments;
+            const residuesIt = Segmentation.transientSegments(unit.hierarchy.residueSegments, set);
             while (chainsIt.hasNext) {
                 const chainSegment = chainsIt.move();
                 l.atom = OrderedSet.getAt(set, chainSegment.start);
                 // test entity and chain
                 if (!entityTest(l) || !chainTest(l)) continue;
 
-                const residuesIt = Segmentation.transientSegments(residues, set, chainSegment);
+                residuesIt.setSegment(chainSegment);
                 while (residuesIt.hasNext) {
                     const residueSegment = residuesIt.move();
                     l.atom = OrderedSet.getAt(set, residueSegment.start);
diff --git a/src/perf-tests/structure.ts b/src/perf-tests/structure.ts
index 2ed618f65..a1d996834 100644
--- a/src/perf-tests/structure.ts
+++ b/src/perf-tests/structure.ts
@@ -235,8 +235,8 @@ export namespace PropertyAccess {
     // }
 
     export async function run() {
-        //const { structures, models } = await readCIF('./examples/1cbs_full.bcif');
-        const { structures, models } = await readCIF('e:/test/quick/1jj2_full.bcif');
+        const { structures, models } = await readCIF('./examples/1cbs_full.bcif');
+        //const { structures, models } = await readCIF('e:/test/quick/3j3q_full.bcif');
         //const { structures, models } = await readCIF('e:/test/quick/3j3q_updated.cif');
 
         console.log('parsed');
-- 
GitLab