From da738d87e6797080647bf5bc047a9410dcd30d0f Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Wed, 29 Aug 2018 11:13:46 -0700 Subject: [PATCH] better handling of missing atoms in trace, block, backbone visuals --- .../structure/visual/nucleotide-block-mesh.ts | 23 ++++++++------ .../visual/util/polymer/backbone-iterator.ts | 13 ++++++-- .../visual/util/polymer/trace-iterator.ts | 31 ++++++++++--------- src/mol-model/structure/util.ts | 4 +-- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts index 0ace3c526..03a2eeb94 100644 --- a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts @@ -82,18 +82,21 @@ async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, props: idx6 = getElementIndexForAtomRole(model, residueIndex, 'trace') } - if (idx1 !== -1 && idx2 !== -1 && idx3 !== -1 && idx4 !== -1 && idx5 !== -1 && idx6 !== -1) { - pos(idx1, p1); pos(idx2, p2); pos(idx3, p3); pos(idx4, p4); pos(idx5, p5); pos(idx6, p6) - Vec3.normalize(v12, Vec3.sub(v12, p2, p1)) - Vec3.normalize(v34, Vec3.sub(v34, p4, p3)) - Vec3.normalize(vC, Vec3.cross(vC, v12, v34)) - Mat4.targetTo(t, p1, p2, vC) - Vec3.scaleAndAdd(center, p1, v12, height / 2 - 0.2) - Mat4.scale(t, t, Vec3.set(sVec, width, depth, height)) - Mat4.setTranslation(t, center) + if (idx5 !== -1 && idx6 !== -1) { + pos(idx5, p5); pos(idx6, p6) builder.setGroup(SortedArray.findPredecessorIndex(elements, idx6)) - builder.add(t, box) addCylinder(builder, p5, p6, 1, { radiusTop: 0.2, radiusBottom: 0.2 }) + if (idx1 !== -1 && idx2 !== -1 && idx3 !== -1 && idx4 !== -1) { + pos(idx1, p1); pos(idx2, p2); pos(idx3, p3); pos(idx4, p4); + Vec3.normalize(v12, Vec3.sub(v12, p2, p1)) + Vec3.normalize(v34, Vec3.sub(v34, p4, p3)) + Vec3.normalize(vC, Vec3.cross(vC, v12, v34)) + Mat4.targetTo(t, p1, p2, vC) + Vec3.scaleAndAdd(center, p1, v12, height / 2 - 0.2) + Mat4.scale(t, t, Vec3.set(sVec, width, depth, height)) + Mat4.setTranslation(t, center) + builder.add(t, box) + } } } diff --git a/src/mol-geo/representation/structure/visual/util/polymer/backbone-iterator.ts b/src/mol-geo/representation/structure/visual/util/polymer/backbone-iterator.ts index eaa3c029c..31170313f 100644 --- a/src/mol-geo/representation/structure/visual/util/polymer/backbone-iterator.ts +++ b/src/mol-geo/representation/structure/visual/util/polymer/backbone-iterator.ts @@ -10,6 +10,7 @@ import Iterator from 'mol-data/iterator'; import SortedRanges from 'mol-data/int/sorted-ranges'; import { getElementIndexForAtomRole } from 'mol-model/structure/util'; import { getPolymerRanges } from '../polymer'; +import { AtomRole } from 'mol-model/structure/model/types'; /** Iterates over consecutive pairs of residues/coarse elements in polymers */ export function PolymerBackboneIterator(unit: Unit): Iterator<PolymerBackbonePair> { @@ -43,13 +44,19 @@ export class AtomicPolymerBackboneIterator implements Iterator<PolymerBackbonePa private residueSegment: Segmentation.Segment<ResidueIndex> hasNext: boolean = false; + private getElementIndex(residueIndex: ResidueIndex, atomRole: AtomRole) { + const { atomicHierarchy } = this.unit.model + const elementIndex = getElementIndexForAtomRole(this.unit.model, residueIndex, atomRole) + return elementIndex === -1 ? atomicHierarchy.residueAtomSegments.offsets[residueIndex] : elementIndex + } + move() { if (this.state === AtomicPolymerBackboneIteratorState.nextPolymer) { while (this.polymerIt.hasNext) { this.residueIt.setSegment(this.polymerIt.move()); if (this.residueIt.hasNext) { this.residueSegment = this.residueIt.move() - this.value.centerB.element = getElementIndexForAtomRole(this.unit.model, this.residueSegment.index, 'trace') + this.value.centerB.element = this.getElementIndex(this.residueSegment.index, 'trace') this.state = AtomicPolymerBackboneIteratorState.nextResidue break } @@ -59,7 +66,7 @@ export class AtomicPolymerBackboneIterator implements Iterator<PolymerBackbonePa if (this.state === AtomicPolymerBackboneIteratorState.nextResidue) { this.residueSegment = this.residueIt.move() this.value.centerA.element = this.value.centerB.element - this.value.centerB.element = getElementIndexForAtomRole(this.unit.model, this.residueSegment.index, 'trace') + this.value.centerB.element = this.getElementIndex(this.residueSegment.index, 'trace') if (!this.residueIt.hasNext) { if (this.unit.model.atomicHierarchy.cyclicPolymerMap.has(this.residueSegment.index)) { this.state = AtomicPolymerBackboneIteratorState.cycle @@ -71,7 +78,7 @@ export class AtomicPolymerBackboneIterator implements Iterator<PolymerBackbonePa } else if (this.state === AtomicPolymerBackboneIteratorState.cycle) { const { cyclicPolymerMap } = this.unit.model.atomicHierarchy this.value.centerA.element = this.value.centerB.element - this.value.centerB.element = getElementIndexForAtomRole(this.unit.model, cyclicPolymerMap.get(this.residueSegment.index)!, 'trace') + this.value.centerB.element = this.getElementIndex(cyclicPolymerMap.get(this.residueSegment.index)!, 'trace') // TODO need to advance to a polymer that has two or more residues (can't assume it has) this.state = AtomicPolymerBackboneIteratorState.nextPolymer } diff --git a/src/mol-geo/representation/structure/visual/util/polymer/trace-iterator.ts b/src/mol-geo/representation/structure/visual/util/polymer/trace-iterator.ts index df4cfabc5..e4b98c009 100644 --- a/src/mol-geo/representation/structure/visual/util/polymer/trace-iterator.ts +++ b/src/mol-geo/representation/structure/visual/util/polymer/trace-iterator.ts @@ -89,24 +89,25 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> this.residueSegmentMax = index[this.unit.elements[polymerSegment.end - 1]] } - private getAtomIndex(residueIndex: ResidueIndex, atomRole: AtomRole) { - const { cyclicPolymerMap } = this.unit.model.atomicHierarchy + private getElementIndex(residueIndex: ResidueIndex, atomRole: AtomRole) { + const { atomicHierarchy } = this.unit.model if (residueIndex < this.residueSegmentMin) { - const cyclicIndex = cyclicPolymerMap.get(this.residueSegmentMin) + const cyclicIndex = atomicHierarchy.cyclicPolymerMap.get(this.residueSegmentMin) if (cyclicIndex !== undefined) { residueIndex = cyclicIndex - (this.residueSegmentMin - residueIndex - 1) as ResidueIndex } else { residueIndex = this.residueSegmentMin } } else if (residueIndex > this.residueSegmentMax) { - const cyclicIndex = cyclicPolymerMap.get(this.residueSegmentMax) + const cyclicIndex = atomicHierarchy.cyclicPolymerMap.get(this.residueSegmentMax) if (cyclicIndex !== undefined) { residueIndex = cyclicIndex + (residueIndex - this.residueSegmentMax - 1) as ResidueIndex } else { residueIndex = this.residueSegmentMax } } - return getElementIndexForAtomRole(this.unit.model, residueIndex, atomRole) + const elementIndex = getElementIndexForAtomRole(this.unit.model, residueIndex, atomRole) + return elementIndex === -1 ? atomicHierarchy.residueAtomSegments.offsets[residueIndex] : elementIndex } private setControlPoint(out: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, residueIndex: ResidueIndex) { @@ -135,19 +136,19 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> if (this.state === AtomicPolymerTraceIteratorState.nextResidue) { const { index: residueIndex } = residueIt.move(); - value.center.element = this.getAtomIndex(residueIndex, 'trace') + value.center.element = this.getElementIndex(residueIndex, 'trace') - this.pos(this.p0, this.getAtomIndex(residueIndex - 3 as ResidueIndex, 'trace')) - this.pos(this.p1, this.getAtomIndex(residueIndex - 2 as ResidueIndex, 'trace')) - this.pos(this.p2, this.getAtomIndex(residueIndex - 1 as ResidueIndex, 'trace')) - this.pos(this.p3, this.getAtomIndex(residueIndex, 'trace')) - this.pos(this.p4, this.getAtomIndex(residueIndex + 1 as ResidueIndex, 'trace')) - this.pos(this.p5, this.getAtomIndex(residueIndex + 2 as ResidueIndex, 'trace')) - this.pos(this.p6, this.getAtomIndex(residueIndex + 3 as ResidueIndex, 'trace')) + this.pos(this.p0, this.getElementIndex(residueIndex - 3 as ResidueIndex, 'trace')) + this.pos(this.p1, this.getElementIndex(residueIndex - 2 as ResidueIndex, 'trace')) + this.pos(this.p2, this.getElementIndex(residueIndex - 1 as ResidueIndex, 'trace')) + this.pos(this.p3, this.getElementIndex(residueIndex, 'trace')) + this.pos(this.p4, this.getElementIndex(residueIndex + 1 as ResidueIndex, 'trace')) + this.pos(this.p5, this.getElementIndex(residueIndex + 2 as ResidueIndex, 'trace')) + this.pos(this.p6, this.getElementIndex(residueIndex + 3 as ResidueIndex, 'trace')) // this.pos(this.v01, this.getAtomIndex(residueIndex - 2 as ResidueIndex, 'direction')) - this.pos(this.v12, this.getAtomIndex(residueIndex - 1 as ResidueIndex, 'direction')) - this.pos(this.v23, this.getAtomIndex(residueIndex, 'direction')) + this.pos(this.v12, this.getElementIndex(residueIndex - 1 as ResidueIndex, 'direction')) + this.pos(this.v23, this.getElementIndex(residueIndex, 'direction')) // this.pos(this.v34, this.getAtomIndex(residueIndex + 1 as ResidueIndex, 'direction')) this.value.secStrucType = this.unit.model.properties.secondaryStructure.type[residueIndex] diff --git a/src/mol-model/structure/util.ts b/src/mol-model/structure/util.ts index a20abb42e..ba416db93 100644 --- a/src/mol-model/structure/util.ts +++ b/src/mol-model/structure/util.ts @@ -26,13 +26,13 @@ export function getAtomIdForAtomRole(moleculeType: MoleculeType, atomRole: AtomR return '' } -export function getElementIndexForAtomId(model: Model, rI: ResidueIndex, atomId: string): ElementIndex { +export function getElementIndexForAtomId(model: Model, rI: ResidueIndex, atomId: string): ElementIndex | -1 { const { offsets } = model.atomicHierarchy.residueAtomSegments const { label_atom_id } = model.atomicHierarchy.atoms for (let j = offsets[rI], _j = offsets[rI + 1]; j < _j; j++) { if (label_atom_id.value(j) === atomId) return j as ElementIndex } - return offsets[rI] as ElementIndex + return -1 } export function getElementIndexForAtomRole(model: Model, rI: ResidueIndex, atomRole: AtomRole) { -- GitLab