From ed1ae71f71806721438d241cc0a8800bca2b4f7e Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Sun, 18 Aug 2019 13:01:31 -0700 Subject: [PATCH] optimized repr loci iteration, marking and extendToWholeChains --- src/mol-model/structure/structure/element.ts | 13 +++++-- .../structure/units-representation.ts | 2 ++ .../structure/visual/util/nucleotide.ts | 36 ++++++++++++------- src/mol-repr/structure/visual/util/polymer.ts | 32 ++++++++++------- 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts index eb0cb0577..ca472c660 100644 --- a/src/mol-model/structure/structure/element.ts +++ b/src/mol-model/structure/structure/element.ts @@ -282,7 +282,7 @@ namespace StructureElement { const elements: Loci['elements'][0][] = []; for (const lociElement of loci.elements) { - const newIndices: UnitIndex[] = []; + const _newIndices: UnitIndex[] = []; const unitElements = lociElement.unit.elements; const { index: chainIndex, offsets: chainOffsets } = getChainSegments(lociElement.unit) @@ -298,11 +298,18 @@ namespace StructureElement { for (let j = chainOffsets[cI], _j = chainOffsets[cI + 1]; j < _j; j++) { const idx = OrderedSet.indexOf(unitElements, j); - if (idx >= 0) newIndices[newIndices.length] = idx as UnitIndex; + if (idx >= 0) _newIndices[_newIndices.length] = idx as UnitIndex; } } - elements[elements.length] = { unit: lociElement.unit, indices: SortedArray.ofSortedArray(newIndices) }; + let newIndices: OrderedSet<UnitIndex> + if (_newIndices.length > 12 && _newIndices[_newIndices.length - 1] - _newIndices[0] === _newIndices.length - 1) { + newIndices = Interval.ofRange(_newIndices[0], _newIndices[_newIndices.length - 1]) + } else { + newIndices = SortedArray.ofSortedArray(_newIndices) + } + + elements[elements.length] = { unit: lociElement.unit, indices: newIndices }; } return Loci(loci.structure, elements); diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts index cbc6eb000..63e206604 100644 --- a/src/mol-repr/structure/units-representation.ts +++ b/src/mol-repr/structure/units-representation.ts @@ -169,8 +169,10 @@ export function UnitsRepresentation<P extends UnitsParams>(label: string, ctx: R if (!Structure.areParentsEquivalent(loci.structure, _structure)) return false if (StructureElement.isLoci(loci)) { loci = StructureElement.Loci.remap(loci, _structure) + if (loci.elements.length === 0) return false } else if (Link.isLoci(loci)) { loci = Link.remapLoci(loci, _structure) + if (loci.links.length === 0) return false } visuals.forEach(({ visual }) => { changed = visual.mark(loci, action) || changed diff --git a/src/mol-repr/structure/visual/util/nucleotide.ts b/src/mol-repr/structure/visual/util/nucleotide.ts index e3d968dea..9d9787fb6 100644 --- a/src/mol-repr/structure/visual/util/nucleotide.ts +++ b/src/mol-repr/structure/visual/util/nucleotide.ts @@ -41,6 +41,10 @@ export function getNucleotideElementLoci(pickingId: PickingId, structureGroup: S return EmptyLoci } +/** + * Mark a nucleotide element (e.g. part of a cartoon block) + * - mark only when all its residue's elements are in a loci + */ export function eachNucleotideElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { let changed = false if (!StructureElement.isLoci(loci)) return false @@ -56,19 +60,25 @@ export function eachNucleotideElement(loci: Loci, structureGroup: StructureGroup const unitIdx = group.unitIndexMap.get(e.unit.id) const eUnit = e.unit if (unitIdx !== undefined && Unit.isAtomic(eUnit)) { - // TODO optimized implementation for intervals - OrderedSet.forEach(e.indices, v => { - const rI = index[elements[v]] - const unitIndexMin = OrderedSet.findPredecessorIndex(elements, offsets[rI]) - const unitIndexMax = OrderedSet.findPredecessorIndex(elements, offsets[rI + 1] - 1) - const unitIndexInterval = Interval.ofRange(unitIndexMin, unitIndexMax) - if (!OrderedSet.isSubset(e.indices, unitIndexInterval)) return - const eI = traceElementIndex[rI] - const idx = OrderedSet.indexOf(eUnit.nucleotideElements, eI) - if (idx !== -1) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true - } - }) + // TODO optimized implementation for intervals covering only part of the unit + if (Interval.is(e.indices) && Interval.start(e.indices) === 0 && Interval.end(e.indices) === e.unit.elements.length) { + const start = unitIdx * groupCount; + const end = unitIdx * groupCount + groupCount; + if (apply(Interval.ofBounds(start, end))) changed = true + } else { + OrderedSet.forEach(e.indices, v => { + const rI = index[elements[v]] + const unitIndexMin = OrderedSet.findPredecessorIndex(elements, offsets[rI]) + const unitIndexMax = OrderedSet.findPredecessorIndex(elements, offsets[rI + 1] - 1) + const unitIndexInterval = Interval.ofRange(unitIndexMin, unitIndexMax) + if (!OrderedSet.isSubset(e.indices, unitIndexInterval)) return + const eI = traceElementIndex[rI] + const idx = OrderedSet.indexOf(eUnit.nucleotideElements, eI) + if (idx !== -1) { + if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true + } + }) + } } } return changed diff --git a/src/mol-repr/structure/visual/util/polymer.ts b/src/mol-repr/structure/visual/util/polymer.ts index 401626df0..33f99c023 100644 --- a/src/mol-repr/structure/visual/util/polymer.ts +++ b/src/mol-repr/structure/visual/util/polymer.ts @@ -104,19 +104,25 @@ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, a const unitIdx = group.unitIndexMap.get(e.unit.id) if (unitIdx !== undefined) { if (Unit.isAtomic(e.unit)) { - // TODO optimized implementation for intervals - OrderedSet.forEach(e.indices, v => { - const rI = index[elements[v]] - const unitIndexMin = OrderedSet.findPredecessorIndex(elements, offsets[rI]) - const unitIndexMax = OrderedSet.findPredecessorIndex(elements, offsets[rI + 1] - 1) - const unitIndexInterval = Interval.ofRange(unitIndexMin, unitIndexMax) - if (!OrderedSet.isSubset(e.indices, unitIndexInterval)) return - const eI = traceElementIndex[rI] - const idx = OrderedSet.indexOf(e.unit.polymerElements, eI) - if (idx !== -1) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true - } - }) + // TODO optimized implementation for intervals covering only part of the unit + if (Interval.is(e.indices) && Interval.start(e.indices) === 0 && Interval.end(e.indices) === e.unit.elements.length) { + const start = unitIdx * groupCount; + const end = unitIdx * groupCount + groupCount; + if (apply(Interval.ofBounds(start, end))) changed = true + } else { + OrderedSet.forEach(e.indices, v => { + const rI = index[elements[v]] + const unitIndexMin = OrderedSet.findPredecessorIndex(elements, offsets[rI]) + const unitIndexMax = OrderedSet.findPredecessorIndex(elements, offsets[rI + 1] - 1) + const unitIndexInterval = Interval.ofRange(unitIndexMin, unitIndexMax) + if (!OrderedSet.isSubset(e.indices, unitIndexInterval)) return + const eI = traceElementIndex[rI] + const idx = OrderedSet.indexOf(e.unit.polymerElements, eI) + if (idx !== -1) { + if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true + } + }) + } } else { if (Interval.is(e.indices)) { const start = unitIdx * groupCount + Interval.start(e.indices); -- GitLab