From 456ee97b5fda3913f9ee4f9e95932616ecfcc7df Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Thu, 12 Jul 2018 19:25:49 -0700 Subject: [PATCH] polymer iterator cleanup --- .../visual/polymer-backbone-cylinder.ts | 18 +- .../structure/visual/polymer-trace-mesh.ts | 6 +- .../structure/visual/util/polymer.ts | 297 ++++++------------ 3 files changed, 106 insertions(+), 215 deletions(-) diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts index 21debef67..949d4d9f4 100644 --- a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts @@ -23,6 +23,7 @@ import { createMeshValues, updateMeshValues, updateRenderableState, createRender import { MeshBuilder } from '../../../shape/mesh-builder'; import { getPolymerElementCount, PolymerBackboneIterator } from './util/polymer'; import { getElementLoci, markElement } from './util/element'; +import { Vec3 } from 'mol-math/linear-algebra'; async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit, mesh?: Mesh) { const polymerElementCount = getPolymerElementCount(unit) @@ -32,15 +33,22 @@ async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit // TODO better vertex count estimates const builder = MeshBuilder.create(polymerElementCount * 30, polymerElementCount * 30 / 2, mesh) + const { elements } = unit + const pos = unit.conformation.invariantPosition + const pA = Vec3.zero() + const pB = Vec3.zero() + let i = 0 const polymerBackboneIt = PolymerBackboneIterator(unit) while (polymerBackboneIt.hasNext) { - const { indexA, indexB, posA, posB } = polymerBackboneIt.move() - builder.setId(indexA) // TODO size theme - builder.addCylinder(posA, posB, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 }) - builder.setId(indexB) - builder.addCylinder(posB, posA, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 }) + const { centerA, centerB } = polymerBackboneIt.move() + pos(centerA.element, pA) + pos(centerB.element, pB) + builder.setId(elements[centerA.element]) + builder.addCylinder(pA, pB, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 }) + builder.setId(elements[centerB.element]) + builder.addCylinder(pB, pA, 0.5, { radiusTop: 0.2, radiusBottom: 0.2 }) if (i % 10000 === 0 && ctx.shouldUpdate) { await ctx.update({ message: 'Backbone mesh', current: i, max: polymerElementCount }); diff --git a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts index 027cda9f8..96207c6a3 100644 --- a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts @@ -73,7 +73,7 @@ function interpolateNormals(controlPoints: Helpers.NumberArray, tangentVectors: // console.warn(i, 'flip compared to prev', radToDeg(Math.acos(Vec3.dot(prevNormal, normalVec)))) // } Vec3.copy(prevNormal, normalVec) - + Vec3.normalize(binormalVec, Vec3.cross(binormalVec, tangentVec, normalVec)) Vec3.toArray(binormalVec, binormalVectors, i * 3) } @@ -84,6 +84,8 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me console.log('polymerElementCount', polymerElementCount) if (!polymerElementCount) return Mesh.createEmpty(mesh) + const { elements } = unit + // TODO better vertex count estimates const builder = MeshBuilder.create(polymerElementCount * 30, polymerElementCount * 30 / 2, mesh) const linearSegments = 12 @@ -108,7 +110,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me const polymerTraceIt = PolymerTraceIterator(unit) while (polymerTraceIt.hasNext) { const v = polymerTraceIt.move() - builder.setId(v.index) + builder.setId(elements[v.center.element]) for (let j = 0; j <= linearSegments; ++j) { const t = j * 1.0 / linearSegments; diff --git a/src/mol-geo/representation/structure/visual/util/polymer.ts b/src/mol-geo/representation/structure/visual/util/polymer.ts index 2a6e5eead..9565bd1c4 100644 --- a/src/mol-geo/representation/structure/visual/util/polymer.ts +++ b/src/mol-geo/representation/structure/visual/util/polymer.ts @@ -4,15 +4,14 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Unit, StructureElement, StructureProperties, Model, ElementIndex } from 'mol-model/structure'; +import { Unit, StructureElement, Model, ElementIndex, ResidueIndex } from 'mol-model/structure'; import { Segmentation, OrderedSet, Interval } from 'mol-data/int'; import { MoleculeType, SecondaryStructureType } from 'mol-model/structure/model/types'; import Iterator from 'mol-data/iterator'; import { Vec3 } from 'mol-math/linear-algebra'; -import { SymmetryOperator } from 'mol-math/geometry'; import SortedRanges from 'mol-data/int/sorted-ranges'; -export function getPolymerRanges(unit: Unit) { +export function getPolymerRanges(unit: Unit): SortedRanges<ElementIndex> { switch (unit.kind) { case Unit.Kind.Atomic: return unit.model.atomicHierarchy.polymerRanges case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.polymerRanges @@ -48,78 +47,49 @@ export function getPolymerElementCount(unit: Unit) { return count } -function getTraceName(l: StructureElement) { - const compId = StructureProperties.residue.label_comp_id(l) - const chemCompMap = l.unit.model.properties.chemicalComponentMap - const cc = chemCompMap.get(compId) - const moleculeType = cc ? cc.moleculeType : MoleculeType.unknown - let traceName = '' - if (moleculeType === MoleculeType.protein) { - traceName = 'CA' - } else if (moleculeType === MoleculeType.DNA || moleculeType === MoleculeType.RNA) { - traceName = 'P' - } - return traceName -} - -function setTraceElement(l: StructureElement, residueSegment: Segmentation.Segment) { - const elements = l.unit.elements - l.element = elements[residueSegment.start] - const traceName = getTraceName(l) - - for (let j = residueSegment.start, _j = residueSegment.end; j < _j; j++) { - l.element = elements[j]; - if (StructureProperties.atom.label_atom_id(l) === traceName) return j +function getResidueTypeAtomId(moleculeType: MoleculeType, atomType: 'trace' | 'direction') { + switch (moleculeType) { + case MoleculeType.protein: + switch (atomType) { + case 'trace': return 'CA' + case 'direction': return 'O' + } + break + case MoleculeType.RNA: + switch (atomType) { + case 'trace': return 'C4\'' + case 'direction': return 'C3\'' + } + break + case MoleculeType.DNA: + switch (atomType) { + case 'trace': return 'C3\'' + case 'direction': return 'O4\'' + } + break } - return residueSegment.end - 1 + return '' } - -function getTraceName2(model: Model, residueModelIndex: number) { - const compId = model.atomicHierarchy.residues.label_comp_id.value(residueModelIndex) +function getMoleculeType(model: Model, residueIndex: number) { + const compId = model.atomicHierarchy.residues.label_comp_id.value(residueIndex) const chemCompMap = model.properties.chemicalComponentMap const cc = chemCompMap.get(compId) - const moleculeType = cc ? cc.moleculeType : MoleculeType.unknown - let traceName = '' - if (moleculeType === MoleculeType.protein) { - traceName = 'CA' - } else if (moleculeType === MoleculeType.DNA) { - // traceName = 'P' - traceName = 'C3\'' - } else if (moleculeType === MoleculeType.RNA) { - // traceName = 'P' - traceName = 'C4\'' - } - return traceName + return cc ? cc.moleculeType : MoleculeType.unknown } -// TODO fix type -function getTraceElement2(model: Model, residueModelSegment: Segmentation.Segment<number>) { - const traceName = getTraceName2(model, residueModelSegment.index) - - for (let j = residueModelSegment.start, _j = residueModelSegment.end; j < _j; j++) { - if (model.atomicHierarchy.atoms.label_atom_id.value(j) === traceName) return j +function getElementIndexForAtomId(unit: Unit.Atomic, residueSegment: Segmentation.Segment, atomId: string) { + const elements = unit.elements + const { label_atom_id } = unit.model.atomicHierarchy.atoms + for (let j = residueSegment.start, _j = residueSegment.end; j < _j; j++) { + if (label_atom_id.value(elements[j]) === atomId) return j as ElementIndex } - console.log(`trace name element "${traceName}" not found`, { ...residueModelSegment }) - return residueModelSegment.start + return residueSegment.end - 1 as ElementIndex } -function getDirectionName2(model: Model, residueModelIndex: number) { - const compId = model.atomicHierarchy.residues.label_comp_id.value(residueModelIndex) - const chemCompMap = model.properties.chemicalComponentMap - const cc = chemCompMap.get(compId) - const moleculeType = cc ? cc.moleculeType : MoleculeType.unknown - let traceName = '' - if (moleculeType === MoleculeType.protein) { - traceName = 'O' - } else if (moleculeType === MoleculeType.DNA) { - traceName = 'O4\'' - } else if (moleculeType === MoleculeType.RNA) { - traceName = 'C3\'' - } else { - console.log('molecule type unknown', Number.isInteger(residueModelIndex) ? compId : residueModelIndex, chemCompMap) - } - return traceName +function getResidueTypeAtomIdElementIndex(unit: Unit.Atomic, residueSegment: Segmentation.Segment, type: 'trace' | 'direction') { + const atomId = getResidueTypeAtomId(getMoleculeType(unit.model, residueSegment.index), type) + return getElementIndexForAtomId(unit, residueSegment, atomId) } // function residueLabel(model: Model, rI: number) { @@ -130,18 +100,6 @@ function getDirectionName2(model: Model, residueModelIndex: number) { // return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}` // } -// TODO fix type -function getDirectionElement2(model: Model, residueModelSegment: Segmentation.Segment<number>) { - const traceName = getDirectionName2(model, residueModelSegment.index) - - for (let j = residueModelSegment.start, _j = residueModelSegment.end; j < _j; j++) { - if (model.atomicHierarchy.atoms.label_atom_id.value(j) === traceName) return j - } - // console.log('direction name element not found', { ...residueModelSegment }) - return residueModelSegment.start -} - - /** Iterates over consecutive pairs of residues/coarse elements in polymers */ export function PolymerBackboneIterator(unit: Unit): Iterator<PolymerBackbonePair> { switch (unit.kind) { @@ -155,20 +113,12 @@ export function PolymerBackboneIterator(unit: Unit): Iterator<PolymerBackbonePai interface PolymerBackbonePair { centerA: StructureElement centerB: StructureElement - indexA: number - indexB: number - posA: Vec3 - posB: Vec3 } function createPolymerBackbonePair (unit: Unit) { return { centerA: StructureElement.create(unit), centerB: StructureElement.create(unit), - indexA: 0, - indexB: 0, - posA: Vec3.zero(), - posB: Vec3.zero() } } @@ -176,29 +126,19 @@ const enum AtomicPolymerBackboneIteratorState { nextPolymer, firstResidue, nextR export class AtomicPolymerBackboneIterator<T extends number = number> implements Iterator<PolymerBackbonePair> { private value: PolymerBackbonePair - private polymerIt: SortedRanges.Iterator<ElementIndex> - private residueIt: Segmentation.SegmentIterator<number> // TODO specific type - private polymerSegment: Segmentation.Segment<ElementIndex> + private residueIt: Segmentation.SegmentIterator<ResidueIndex> private state: AtomicPolymerBackboneIteratorState = AtomicPolymerBackboneIteratorState.nextPolymer - private pos: SymmetryOperator.CoordinateMapper - hasNext: boolean = false; move() { - const { residueIt, polymerIt, value, pos } = this - if (this.state === AtomicPolymerBackboneIteratorState.nextPolymer) { - while (polymerIt.hasNext) { - this.polymerSegment = polymerIt.move(); - // console.log('polymerSegment', this.polymerSegment) - residueIt.setSegment(this.polymerSegment); - - const residueSegment = residueIt.move(); - // console.log('first residueSegment', residueSegment, residueIt.hasNext) - if (residueIt.hasNext) { - value.indexB = setTraceElement(value.centerB, residueSegment) - pos(value.centerB.element, value.posB) + while (this.polymerIt.hasNext) { + const residueSegment = this.polymerIt.move() + this.residueIt.setSegment(residueSegment); + if (this.residueIt.hasNext) { + this.value.centerB.element = getResidueTypeAtomIdElementIndex(this.unit, residueSegment, 'trace') + // setTraceElement(this.value.centerB, this.residueIt.move()) this.state = AtomicPolymerBackboneIteratorState.nextResidue break } @@ -206,36 +146,23 @@ export class AtomicPolymerBackboneIterator<T extends number = number> implements } if (this.state === AtomicPolymerBackboneIteratorState.nextResidue) { - const residueSegment = residueIt.move(); - // console.log('next residueSegment', residueSegment) - value.centerA.element = value.centerB.element - value.indexA = value.indexB - Vec3.copy(value.posA, value.posB) - value.indexB = setTraceElement(value.centerB, residueSegment) - pos(value.centerB.element, value.posB) - - if (!residueIt.hasNext) { + this.value.centerA.element = this.value.centerB.element + this.value.centerB.element = getResidueTypeAtomIdElementIndex(this.unit, this.residueIt.move(), 'trace') + // setTraceElement(this.value.centerB, this.residueIt.move()) + if (!this.residueIt.hasNext) { // TODO need to advance to a polymer that has two or more residues (can't assume it has) this.state = AtomicPolymerBackboneIteratorState.nextPolymer } } - this.hasNext = residueIt.hasNext || polymerIt.hasNext - - // console.log('hasNext', this.hasNext) - // console.log('value', this.value) - + this.hasNext = this.residueIt.hasNext || this.polymerIt.hasNext return this.value; } - constructor(unit: Unit.Atomic) { - const { residueAtomSegments } = unit.model.atomicHierarchy - // console.log('unit.elements', OrderedSet.toArray(unit.elements)) + constructor(private unit: Unit.Atomic) { this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements) - this.residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements) - this.pos = unit.conformation.invariantPosition + this.residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, unit.elements) this.value = createPolymerBackbonePair(unit) - this.hasNext = this.residueIt.hasNext && this.polymerIt.hasNext } } @@ -244,29 +171,20 @@ const enum CoarsePolymerBackboneIteratorState { nextPolymer, nextElement } export class CoarsePolymerBackboneIterator<T extends number = number> implements Iterator<PolymerBackbonePair> { private value: PolymerBackbonePair - private polymerIt: SortedRanges.Iterator<ElementIndex> private polymerSegment: Segmentation.Segment<ElementIndex> private state: CoarsePolymerBackboneIteratorState = CoarsePolymerBackboneIteratorState.nextPolymer - private pos: SymmetryOperator.CoordinateMapper private elementIndex: number - hasNext: boolean = false; move() { - const { polymerIt, value, pos } = this - if (this.state === CoarsePolymerBackboneIteratorState.nextPolymer) { - if (polymerIt.hasNext) { - this.polymerSegment = polymerIt.move(); - console.log('polymer', this.polymerSegment) + if (this.polymerIt.hasNext) { + this.polymerSegment = this.polymerIt.move(); this.elementIndex = this.polymerSegment.start - this.elementIndex += 1 + // this.elementIndex += 1 if (this.elementIndex + 1 < this.polymerSegment.end) { - value.centerB.element = value.centerB.unit.elements[this.elementIndex] - value.indexB = this.elementIndex - pos(value.centerB.element, value.posB) - + this.value.centerB.element = this.value.centerB.unit.elements[this.elementIndex] this.state = CoarsePolymerBackboneIteratorState.nextElement } else { this.state = CoarsePolymerBackboneIteratorState.nextPolymer @@ -276,31 +194,20 @@ export class CoarsePolymerBackboneIterator<T extends number = number> implements if (this.state === CoarsePolymerBackboneIteratorState.nextElement) { this.elementIndex += 1 - value.centerA.element = value.centerB.element - value.indexA = value.indexB - Vec3.copy(value.posA, value.posB) - - value.centerB.element = value.centerB.unit.elements[this.elementIndex] - value.indexB = this.elementIndex - pos(value.centerB.element, value.posB) - + this.value.centerA.element = this.value.centerB.element + this.value.centerB.element = this.value.centerB.unit.elements[this.elementIndex] if (this.elementIndex + 1 >= this.polymerSegment.end) { this.state = CoarsePolymerBackboneIteratorState.nextPolymer } } - this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || polymerIt.hasNext + this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || this.polymerIt.hasNext return this.value; } constructor(unit: Unit.Spheres | Unit.Gaussians) { this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements); - - this.pos = unit.conformation.invariantPosition this.value = createPolymerBackbonePair(unit) - - console.log('CoarsePolymerBackboneIterator', this.polymerIt.hasNext) - this.hasNext = this.polymerIt.hasNext } } @@ -323,37 +230,19 @@ export function PolymerTraceIterator(unit: Unit): Iterator<PolymerTraceElement> interface PolymerTraceElement { center: StructureElement - index: number - first: boolean - last: boolean + first: boolean, last: boolean secStrucType: SecondaryStructureType - - t0: Vec3 - t1: Vec3 - t2: Vec3 - t3: Vec3 - t4: Vec3 - - d12: Vec3 - d23: Vec3 + t0: Vec3, t1: Vec3, t2: Vec3, t3: Vec3, t4: Vec3 + d12: Vec3, d23: Vec3 } function createPolymerTraceElement (unit: Unit): PolymerTraceElement { return { center: StructureElement.create(unit), - index: 0, - first: false, - last: false, + first: false, last: false, secStrucType: SecondaryStructureType.create(SecondaryStructureType.Flag.NA), - - t0: Vec3.zero(), - t1: Vec3.zero(), - t2: Vec3.zero(), - t3: Vec3.zero(), - t4: Vec3.zero(), - - d12: Vec3.zero(), - d23: Vec3.zero(), + t0: Vec3.zero(), t1: Vec3.zero(), t2: Vec3.zero(), t3: Vec3.zero(), t4: Vec3.zero(), + d12: Vec3.zero(), d23: Vec3.zero(), } } @@ -372,17 +261,13 @@ function setSegment (outSegment: Segmentation.Segment<number>, index: number, se export class AtomicPolymerTraceIterator<T extends number = number> implements Iterator<PolymerTraceElement> { private value: PolymerTraceElement - private polymerIt: SortedRanges.Iterator<ElementIndex> - private residueIt: Segmentation.SegmentIterator<number> // TODO specialize type - private residueSegmentMin: number - private residueSegmentMax: number + private residueIt: Segmentation.SegmentIterator<ResidueIndex> + private residueAtomSegmentMin: number + private residueAtomSegmentMax: number private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer - private residueSegments: Segmentation<ElementIndex> - - private tmpSegment: Segmentation.Segment<number> - - private unit: Unit.Atomic + private residueAtomSegments: Segmentation<ElementIndex, ResidueIndex> + private tmpSegment: Segmentation.Segment<ResidueIndex> hasNext: boolean = false; @@ -396,8 +281,8 @@ export class AtomicPolymerTraceIterator<T extends number = number> implements It const { polymerRanges, residueAtomSegments } = this.unit.model.atomicHierarchy const sMin = polymerRanges[polymerSegment.index * 2] const sMax = polymerRanges[polymerSegment.index * 2 + 1] - this.residueSegmentMin = residueAtomSegments.index[sMin] - this.residueSegmentMax = residueAtomSegments.index[sMax] + this.residueAtomSegmentMin = residueAtomSegments.index[sMin] + this.residueAtomSegmentMax = residueAtomSegments.index[sMax] } move() { @@ -417,32 +302,32 @@ export class AtomicPolymerTraceIterator<T extends number = number> implements It } if (this.state === AtomicPolymerTraceIteratorState.nextResidue) { - const { tmpSegment, residueSegments, residueSegmentMin, residueSegmentMax } = this + const { tmpSegment, residueAtomSegments, residueAtomSegmentMin, residueAtomSegmentMax } = this const residueSegment = residueIt.move(); const resSegIdx = residueSegment.index // console.log(residueLabel(this.unit.model, resSegIdx), resSegIdx, this.unit.model.properties.secondaryStructure.type[resSegIdx]) - value.index = setTraceElement(value.center, residueSegment) + value.center.element = getResidueTypeAtomIdElementIndex(this.unit, residueSegment, 'trace') - setSegment(tmpSegment, resSegIdx - 2, residueSegments, residueSegmentMin, residueSegmentMax) - this.pos(value.t0, getTraceElement2(this.unit.model, tmpSegment)) + setSegment(tmpSegment, resSegIdx - 2, residueAtomSegments, residueAtomSegmentMin, residueAtomSegmentMax) + this.pos(value.t0, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'trace')) - setSegment(tmpSegment, resSegIdx - 1, residueSegments, residueSegmentMin, residueSegmentMax) - this.pos(value.t1, getTraceElement2(this.unit.model, tmpSegment)) - this.pos(value.d12, getDirectionElement2(this.unit.model, tmpSegment)) + setSegment(tmpSegment, resSegIdx - 1, residueAtomSegments, residueAtomSegmentMin, residueAtomSegmentMax) + this.pos(value.t1, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'trace')) + this.pos(value.d12, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'direction')) - setSegment(tmpSegment, resSegIdx, residueSegments, residueSegmentMin, residueSegmentMax) + setSegment(tmpSegment, resSegIdx, residueAtomSegments, residueAtomSegmentMin, residueAtomSegmentMax) value.secStrucType = this.unit.model.properties.secondaryStructure.type[resSegIdx] - this.pos(value.t2, getTraceElement2(this.unit.model, tmpSegment)) - this.pos(value.d23, getDirectionElement2(this.unit.model, tmpSegment)) + this.pos(value.t2, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'trace')) + this.pos(value.d23, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'direction')) - setSegment(tmpSegment, resSegIdx + 1, residueSegments, residueSegmentMin, residueSegmentMax) - this.pos(value.t3, getTraceElement2(this.unit.model, tmpSegment)) + setSegment(tmpSegment, resSegIdx + 1, residueAtomSegments, residueAtomSegmentMin, residueAtomSegmentMax) + this.pos(value.t3, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'trace')) - setSegment(tmpSegment, resSegIdx + 2, residueSegments, residueSegmentMin, residueSegmentMax) - this.pos(value.t4, getTraceElement2(this.unit.model, tmpSegment)) + setSegment(tmpSegment, resSegIdx + 2, residueAtomSegments, residueAtomSegmentMin, residueAtomSegmentMax) + this.pos(value.t4, getResidueTypeAtomIdElementIndex(this.unit, tmpSegment, 'trace')) - value.first = resSegIdx === residueSegmentMin - value.last = resSegIdx === residueSegmentMax + value.first = resSegIdx === residueAtomSegmentMin + value.last = resSegIdx === residueAtomSegmentMax if (!residueIt.hasNext) { this.state = AtomicPolymerTraceIteratorState.nextPolymer @@ -454,17 +339,13 @@ export class AtomicPolymerTraceIterator<T extends number = number> implements It return this.value; } - constructor(unit: Unit.Atomic) { - const { residueAtomSegments } = unit.model.atomicHierarchy + constructor(private unit: Unit.Atomic) { + this.residueAtomSegments = unit.model.atomicHierarchy.residueAtomSegments this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements) - this.residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements); - this.residueSegments = residueAtomSegments + this.residueIt = Segmentation.transientSegments(this.residueAtomSegments, unit.elements); this.value = createPolymerTraceElement(unit) + this.tmpSegment = { index: 0 as ResidueIndex, start: 0 as ElementIndex, end: 0 as ElementIndex } this.hasNext = this.residueIt.hasNext && this.polymerIt.hasNext - - this.tmpSegment = { index: 0, start: 0 as ElementIndex, end: 0 as ElementIndex } - - this.unit = unit } } -- GitLab