Skip to content
Snippets Groups Projects
Commit 40c82387 authored by Alexander Rose's avatar Alexander Rose
Browse files

added support for cyclic atomic polymers

parent cad35f7c
Branches
Tags
No related merge requests found
......@@ -25,8 +25,7 @@ import { getElementLoci, markElement } from './util/element';
import { Vec3, Mat4 } from 'mol-math/linear-algebra';
import { Segmentation, SortedArray } from 'mol-data/int';
import { MoleculeType, isNucleic, isPurinBase, isPyrimidineBase } from 'mol-model/structure/model/types';
import { getElementIndexForAtomId } from 'mol-model/structure/util';
import { getElementIndexForResidueTypeAtomId } from './util/polymer';
import { getElementIndexForAtomId, getElementIndexForAtomRole } from 'mol-model/structure/util';
async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, mesh?: Mesh) {
if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
......@@ -77,7 +76,7 @@ async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, mesh?:
idx3 = getElementIndexForAtomId(model, residueIndex, 'C6')
idx4 = getElementIndexForAtomId(model, residueIndex, 'C2')
idx5 = getElementIndexForAtomId(model, residueIndex, 'N9')
idx6 = getElementIndexForResidueTypeAtomId(model, residueIndex, 'trace')
idx6 = getElementIndexForAtomRole(model, residueIndex, 'trace')
} else if (isPyrimidineBase(compId)) {
height = 3.0
idx1 = getElementIndexForAtomId(model, residueIndex, 'N3')
......@@ -85,7 +84,7 @@ async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, mesh?:
idx3 = getElementIndexForAtomId(model, residueIndex, 'C4')
idx4 = getElementIndexForAtomId(model, residueIndex, 'C2')
idx5 = getElementIndexForAtomId(model, residueIndex, 'N1')
idx6 = getElementIndexForResidueTypeAtomId(model, residueIndex, 'trace')
idx6 = getElementIndexForAtomRole(model, residueIndex, 'trace')
}
if (idx1 !== -1 && idx2 !== -1 && idx3 !== -1 && idx4 !== -1 && idx5 !== -1 && idx6 !== -1) {
......
......@@ -4,14 +4,14 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit, StructureElement, Model, ElementIndex, ResidueIndex } from 'mol-model/structure';
import { Unit, StructureElement, ElementIndex, ResidueIndex } from 'mol-model/structure';
import { Segmentation, OrderedSet, Interval, SortedArray } from 'mol-data/int';
import { MoleculeType, SecondaryStructureType } from 'mol-model/structure/model/types';
import { MoleculeType, SecondaryStructureType, AtomRole } from 'mol-model/structure/model/types';
import Iterator from 'mol-data/iterator';
import { Vec3 } from 'mol-math/linear-algebra';
import SortedRanges from 'mol-data/int/sorted-ranges';
import { CoarseSphereConformation, CoarseGaussianConformation } from 'mol-model/structure/model/properties/coarse';
import { getElementIndexForAtomId, getMoleculeType } from 'mol-model/structure/util';
import { getMoleculeType, getElementIndexForAtomRole } from 'mol-model/structure/util';
export function getPolymerRanges(unit: Unit): SortedRanges<ElementIndex> {
switch (unit.kind) {
......@@ -68,34 +68,7 @@ export function getPolymerGapCount(unit: Unit) {
return count
}
export 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 'C1\''
}
break
}
return ''
}
export function getElementIndexForResidueTypeAtomId(model: Model, rI: ResidueIndex, atomType: 'trace' | 'direction') {
const atomId = getResidueTypeAtomId(getMoleculeType(model, rI), atomType)
return getElementIndexForAtomId(model, rI, atomId)
}
/** Iterates over consecutive pairs of residues/coarse elements in polymers */
export function PolymerBackboneIterator(unit: Unit): Iterator<PolymerBackbonePair> {
......@@ -119,21 +92,22 @@ function createPolymerBackbonePair (unit: Unit) {
}
}
const enum AtomicPolymerBackboneIteratorState { nextPolymer, firstResidue, nextResidue }
const enum AtomicPolymerBackboneIteratorState { nextPolymer, firstResidue, nextResidue, cycle }
export class AtomicPolymerBackboneIterator implements Iterator<PolymerBackbonePair> {
private value: PolymerBackbonePair
private polymerIt: SortedRanges.Iterator<ElementIndex, ResidueIndex>
private residueIt: Segmentation.SegmentIterator<ResidueIndex>
private state: AtomicPolymerBackboneIteratorState = AtomicPolymerBackboneIteratorState.nextPolymer
private residueSegment: Segmentation.Segment<ResidueIndex>
hasNext: boolean = false;
private getElementIndex(residueIndex: ResidueIndex, atomType: 'trace' | 'direction') {
const index = getElementIndexForResidueTypeAtomId(this.unit.model, residueIndex, atomType)
private getElementIndex(residueIndex: ResidueIndex, atomRole: AtomRole) {
const index = getElementIndexForAtomRole(this.unit.model, residueIndex, atomRole)
// TODO handle case when it returns -1
const elementIndex = SortedArray.indexOf(this.unit.elements, index) as ElementIndex
if (elementIndex === -1) {
console.log('-1', residueIndex, atomType, index)
console.log('-1', residueIndex, atomRole, index)
}
return elementIndex === -1 ? 0 as ElementIndex : elementIndex
}
......@@ -141,10 +115,10 @@ export class AtomicPolymerBackboneIterator implements Iterator<PolymerBackbonePa
move() {
if (this.state === AtomicPolymerBackboneIteratorState.nextPolymer) {
while (this.polymerIt.hasNext) {
const residueSegment = this.polymerIt.move()
this.residueIt.setSegment(residueSegment);
this.residueIt.setSegment(this.polymerIt.move());
if (this.residueIt.hasNext) {
this.value.centerB.element = this.getElementIndex(this.residueIt.move().index, 'trace')
this.residueSegment = this.residueIt.move()
this.value.centerB.element = this.getElementIndex(this.residueSegment.index, 'trace')
this.state = AtomicPolymerBackboneIteratorState.nextResidue
break
}
......@@ -152,15 +126,26 @@ 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 = this.getElementIndex(this.residueIt.move().index, 'trace')
this.value.centerB.element = this.getElementIndex(this.residueSegment.index, 'trace')
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
if (this.unit.model.atomicHierarchy.cyclicPolymerMap.has(this.residueSegment.index)) {
this.state = AtomicPolymerBackboneIteratorState.cycle
} else {
// TODO need to advance to a polymer that has two or more residues (can't assume it has)
this.state = AtomicPolymerBackboneIteratorState.nextPolymer
}
}
} else if (this.state === AtomicPolymerBackboneIteratorState.cycle) {
const { cyclicPolymerMap } = this.unit.model.atomicHierarchy
this.value.centerA.element = this.value.centerB.element
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
}
this.hasNext = this.residueIt.hasNext || this.polymerIt.hasNext
this.hasNext = this.residueIt.hasNext || this.polymerIt.hasNext || this.state === AtomicPolymerBackboneIteratorState.cycle
return this.value;
}
......@@ -243,12 +228,12 @@ export class AtomicPolymerGapIterator implements Iterator<PolymerGapPair> {
private gapIt: SortedRanges.Iterator<ElementIndex, ResidueIndex>
hasNext: boolean = false;
private getElementIndex(residueIndex: ResidueIndex, atomType: 'trace' | 'direction') {
const index = getElementIndexForResidueTypeAtomId(this.unit.model, residueIndex, atomType)
private getElementIndex(residueIndex: ResidueIndex, atomRole: AtomRole) {
const index = getElementIndexForAtomRole(this.unit.model, residueIndex, atomRole)
// TODO handle case when it returns -1
const elementIndex = SortedArray.indexOf(this.unit.elements, index) as ElementIndex
if (elementIndex === -1) {
console.log('-1', residueIndex, atomType, index)
console.log('-1', residueIndex, atomRole, index)
}
return elementIndex === -1 ? 0 as ElementIndex : elementIndex
}
......@@ -363,22 +348,38 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
this.residueSegmentMax = index[this.unit.elements[polymerSegment.end - 1]]
}
private getAtomIndex(residueIndex: number, atomType: 'trace' | 'direction') {
const index = Math.min(Math.max(this.residueSegmentMin, residueIndex), this.residueSegmentMax)
return getElementIndexForResidueTypeAtomId(this.unit.model, index as ResidueIndex, atomType)
private getAtomIndex(residueIndex: ResidueIndex, atomRole: AtomRole) {
const { cyclicPolymerMap } = this.unit.model.atomicHierarchy
if (residueIndex < this.residueSegmentMin) {
const cyclicIndex = 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)
if (cyclicIndex !== undefined) {
residueIndex = cyclicIndex + (residueIndex - this.residueSegmentMax - 1) as ResidueIndex
} else {
residueIndex = this.residueSegmentMax
}
}
return getElementIndexForAtomRole(this.unit.model, residueIndex as ResidueIndex, atomRole)
}
private getElementIndex(residueIndex: number, atomType: 'trace' | 'direction') {
const index = this.getAtomIndex(residueIndex, atomType)
private getElementIndex(residueIndex: ResidueIndex, atomRole: AtomRole) {
const index = this.getAtomIndex(residueIndex, atomRole)
// TODO handle case when it returns -1
const elementIndex = SortedArray.indexOf(this.unit.elements, index) as ElementIndex
if (elementIndex === -1) {
console.log('-1', residueIndex, atomType, index)
console.log('-1', residueIndex, atomRole, index)
}
return elementIndex === -1 ? 0 as ElementIndex : elementIndex
}
private setControlPoint(out: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, residueIndex: number) {
private setControlPoint(out: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, residueIndex: ResidueIndex) {
const ss = this.unit.model.properties.secondaryStructure.type[residueIndex]
if (SecondaryStructureType.is(ss, SecondaryStructureType.Flag.Beta)) {
Vec3.scale(out, Vec3.add(out, p1, Vec3.add(out, p3, Vec3.add(out, p2, p2))), 1/4)
......@@ -387,15 +388,6 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
}
}
// private setDirectionVector(out: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, residueIndex: number) {
// const ss = this.unit.model.properties.secondaryStructure.type[residueIndex]
// if (SecondaryStructureType.is(ss, SecondaryStructureType.Flag.Beta)) {
// Vec3.scale(out, Vec3.add(out, p1, Vec3.add(out, p2, p3)), 1/3)
// } else {
// Vec3.copy(out, p2)
// }
// }
move() {
const { residueIt, polymerIt, value } = this
......@@ -415,29 +407,27 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
const { index: residueIndex } = residueIt.move();
value.center.element = this.getElementIndex(residueIndex, 'trace')
this.pos(this.p0, this.getAtomIndex(residueIndex - 3, 'trace'))
this.pos(this.p1, this.getAtomIndex(residueIndex - 2, 'trace'))
this.pos(this.p2, this.getAtomIndex(residueIndex - 1, '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, 'trace'))
this.pos(this.p5, this.getAtomIndex(residueIndex + 2, 'trace'))
this.pos(this.p6, this.getAtomIndex(residueIndex + 3, '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.v01, this.getAtomIndex(residueIndex - 2, 'direction'))
this.pos(this.v12, this.getAtomIndex(residueIndex - 1, 'direction'))
// 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.v34, this.getAtomIndex(residueIndex + 1, 'direction'))
// this.pos(this.v34, this.getAtomIndex(residueIndex + 1 as ResidueIndex, 'direction'))
this.value.secStrucType = this.unit.model.properties.secondaryStructure.type[residueIndex]
this.setControlPoint(value.t0, this.p0, this.p1, this.p2, residueIndex - 2)
this.setControlPoint(value.t1, this.p1, this.p2, this.p3, residueIndex - 1)
this.setControlPoint(value.t0, this.p0, this.p1, this.p2, residueIndex - 2 as ResidueIndex)
this.setControlPoint(value.t1, this.p1, this.p2, this.p3, residueIndex - 1 as ResidueIndex)
this.setControlPoint(value.t2, this.p2, this.p3, this.p4, residueIndex)
this.setControlPoint(value.t3, this.p3, this.p4, this.p5, residueIndex + 1)
this.setControlPoint(value.t4, this.p4, this.p5, this.p6, residueIndex + 2)
this.setControlPoint(value.t3, this.p3, this.p4, this.p5, residueIndex + 1 as ResidueIndex)
this.setControlPoint(value.t4, this.p4, this.p5, this.p6, residueIndex + 2 as ResidueIndex)
// this.setDirectionVector(value.d12, this.v01, this.v12, this.v23, residueIndex)
// this.setDirectionVector(value.d23, this.v12, this.v23, this.v34, residueIndex + 1)
Vec3.copy(value.d12, this.v12)
Vec3.copy(value.d23, this.v23)
......
......@@ -91,17 +91,15 @@ export function getAtomicHierarchyAndConformation(format: mmCIF_Format, atom_sit
};
}
const conformation = getConformation(atom_site)
const hierarchySegments: AtomicSegments = {
residueAtomSegments: Segmentation.ofOffsets(hierarchyOffsets.residues, Interval.ofBounds(0, atom_site._rowCount)),
chainAtomSegments: Segmentation.ofOffsets(hierarchyOffsets.chains, Interval.ofBounds(0, atom_site._rowCount)),
}
const hierarchyKeys = getAtomicKeys(hierarchyData, entities, hierarchySegments);
const hierarchyRanges = getAtomicRanges(hierarchyData, hierarchySegments, formatData.chemicalComponentMap);
const hierarchyRanges = getAtomicRanges(hierarchyData, hierarchySegments, conformation, formatData.chemicalComponentMap);
const hierarchy: AtomicHierarchy = { ...hierarchyData, ...hierarchyKeys, ...hierarchySegments, ...hierarchyRanges };
return {
sameAsPrevious: false,
hierarchy,
conformation: getConformation(atom_site)
};
return { sameAsPrevious: false, hierarchy, conformation };
}
\ No newline at end of file
......@@ -83,6 +83,7 @@ export interface AtomicKeys {
export interface AtomicRanges {
polymerRanges: SortedRanges<ElementIndex>
gapRanges: SortedRanges<ElementIndex>
cyclicPolymerMap: Map<ResidueIndex, ResidueIndex>
}
type _Hierarchy = AtomicData & AtomicSegments & AtomicKeys & AtomicRanges
......
......@@ -8,15 +8,51 @@ import { AtomicSegments } from '../atomic';
import { AtomicData, AtomicRanges } from '../atomic/hierarchy';
import { Segmentation, Interval } from 'mol-data/int';
import SortedRanges from 'mol-data/int/sorted-ranges';
import { ChemicalComponent } from '../chemical-component';
import { ChemicalComponentMap } from '../chemical-component';
import { MoleculeType, isPolymer } from '../../types';
import { ElementIndex } from '../../indexing';
import { ElementIndex, ResidueIndex } from '../../indexing';
import { getAtomIdForAtomRole } from '../../../util';
import { AtomicConformation } from '../atomic/conformation';
import { Vec3 } from 'mol-math/linear-algebra';
// TODO add gaps at the ends of the chains by comparing to the polymer sequence data
export function getAtomicRanges(data: AtomicData, segments: AtomicSegments, chemicalComponentMap: Map<string, ChemicalComponent>): AtomicRanges {
function getMoleculeType(compId: string, chemicalComponentMap: ChemicalComponentMap) {
const cc = chemicalComponentMap.get(compId)
return cc ? cc.moleculeType : MoleculeType.unknown
}
function getElementIndexForAtomId(rI: ResidueIndex, atomId: string, data: AtomicData, segments: AtomicSegments, ): ElementIndex {
const { offsets } = segments.residueAtomSegments
const { label_atom_id } = data.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
}
function areBackboneConnected(riStart: ResidueIndex, riEnd: ResidueIndex, data: AtomicData, segments: AtomicSegments, conformation: AtomicConformation, chemicalComponentMap: ChemicalComponentMap) {
const { label_comp_id } = data.residues
const mtStart = getMoleculeType(label_comp_id.value(riStart), chemicalComponentMap)
const mtEnd = getMoleculeType(label_comp_id.value(riEnd), chemicalComponentMap)
if (!isPolymer(mtStart) || !isPolymer(mtEnd)) return false
const startId = getAtomIdForAtomRole(mtStart, 'backboneStart')
const endId = getAtomIdForAtomRole(mtEnd, 'backboneEnd')
const eiStart = getElementIndexForAtomId(riStart, startId, data, segments)
const eiEnd = getElementIndexForAtomId(riEnd, endId, data, segments)
const { x, y, z } = conformation
const pStart = Vec3.create(x[eiStart], y[eiStart], z[eiStart])
const pEnd = Vec3.create(x[eiEnd], y[eiEnd], z[eiEnd])
return Vec3.distance(pStart, pEnd) < 2
}
export function getAtomicRanges(data: AtomicData, segments: AtomicSegments, conformation: AtomicConformation, chemicalComponentMap: ChemicalComponentMap): AtomicRanges {
const polymerRanges: number[] = []
const gapRanges: number[] = []
const cyclicPolymerMap = new Map<ResidueIndex, ResidueIndex>()
const chainIt = Segmentation.transientSegments(segments.chainAtomSegments, Interval.ofBounds(0, data.atoms._rowCount))
const residueIt = Segmentation.transientSegments(segments.residueAtomSegments, Interval.ofBounds(0, data.atoms._rowCount))
const { label_seq_id, label_comp_id } = data.residues
......@@ -34,11 +70,17 @@ export function getAtomicRanges(data: AtomicData, segments: AtomicSegments, chem
prevEnd = -1
startIndex = -1
const riStart = segments.residueAtomSegments.index[chainSegment.start]
const riEnd = segments.residueAtomSegments.index[chainSegment.end - 1]
if (areBackboneConnected(riStart, riEnd, data, segments, conformation, chemicalComponentMap)) {
cyclicPolymerMap.set(riStart, riEnd)
cyclicPolymerMap.set(riEnd, riStart)
}
while (residueIt.hasNext) {
const residueSegment = residueIt.move();
const residueIndex = residueSegment.index
const cc = chemicalComponentMap.get(label_comp_id.value(residueIndex))
const moleculeType = cc ? cc.moleculeType : MoleculeType.unknown
const moleculeType = getMoleculeType(label_comp_id.value(residueIndex), chemicalComponentMap)
const seqId = label_seq_id.value(residueIndex)
if (isPolymer(moleculeType)) {
if (startIndex !== -1) {
......@@ -67,6 +109,7 @@ export function getAtomicRanges(data: AtomicData, segments: AtomicSegments, chem
return {
polymerRanges: SortedRanges.ofSortedRanges(polymerRanges as ElementIndex[]),
gapRanges: SortedRanges.ofSortedRanges(gapRanges as ElementIndex[])
gapRanges: SortedRanges.ofSortedRanges(gapRanges as ElementIndex[]),
cyclicPolymerMap
}
}
\ No newline at end of file
......@@ -54,6 +54,45 @@ export const enum MoleculeType {
saccharide
}
const AtomRole = {
trace: '', direction: '', backboneStart: '', backboneEnd: ''
}
export type AtomRole = keyof typeof AtomRole
export const MoleculeTypeAtomRoleId: { [k: number]: { [k in AtomRole]: string } } = {
[MoleculeType.protein]: {
trace: 'CA', // TODO 'BB'
direction: 'O', // TODO 'OC1', 'O1', 'OX1', 'OXT'
backboneStart: 'N',
backboneEnd: 'C'
},
[MoleculeType.RNA]: {
trace: 'C4\'', // TODO 'C4*'
direction: 'C3\'', // 'C3*'
backboneStart: 'P',
backboneEnd: 'O3\'' // TODO 'O3*'
},
[MoleculeType.DNA]: {
trace: 'C3\'', // TODO 'C3*'
direction: 'C1\'', // TODO 'C1*'
backboneStart: 'P',
backboneEnd: 'O3\'' // TODO 'O3*'
}
}
export const ProteinBackboneAtoms = [
'CA', 'C', 'N', 'O',
'O1', 'O2', 'OC1', 'OC2', 'OX1', 'OXT',
'H', 'H1', 'H2', 'H3', 'HA', 'HN',
'BB'
]
export const NucleicBackboneAtoms = [
'P', 'OP1', 'OP2',
'O2\'', 'O3\'', 'O4\'', 'O5\'', 'C1\'', 'C2\'', 'C3\'', 'C4\'', 'C5\'',
'O2*', 'O3*', 'O4*', 'O5*', 'C1*', 'C2*', 'C3*', 'C4*', 'C5*'
]
/** Chemical component types as defined in the mmCIF CCD */
export enum ComponentType {
// protein
......
......@@ -5,7 +5,7 @@
*/
import { Model, ResidueIndex, ElementIndex } from './model';
import { MoleculeType } from './model/types';
import { MoleculeType, AtomRole, MoleculeTypeAtomRoleId } from './model/types';
export function getMoleculeType(model: Model, rI: ResidueIndex) {
const compId = model.atomicHierarchy.residues.label_comp_id.value(rI)
......@@ -14,6 +14,15 @@ export function getMoleculeType(model: Model, rI: ResidueIndex) {
return cc ? cc.moleculeType : MoleculeType.unknown
}
export function getAtomIdForAtomRole(moleculeType: MoleculeType, atomRole: AtomRole) {
const m = MoleculeTypeAtomRoleId[moleculeType]
if (m !== undefined) {
const a = m[atomRole]
if (a !== undefined) return a
}
return ''
}
export function getElementIndexForAtomId(model: Model, rI: ResidueIndex, atomId: string): ElementIndex {
const { offsets } = model.atomicHierarchy.residueAtomSegments
const { label_atom_id } = model.atomicHierarchy.atoms
......@@ -23,6 +32,11 @@ export function getElementIndexForAtomId(model: Model, rI: ResidueIndex, atomId:
return offsets[rI] as ElementIndex
}
export function getElementIndexForAtomRole(model: Model, rI: ResidueIndex, atomRole: AtomRole) {
const atomId = getAtomIdForAtomRole(getMoleculeType(model, rI), atomRole)
return getElementIndexForAtomId(model, rI, atomId)
}
export function residueLabel(model: Model, rI: number) {
const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy
const { label_comp_id, label_seq_id } = residues
......
......@@ -83,7 +83,7 @@ export class Stage {
// this.loadPdbid('2np2') // dna
// this.loadPdbid('1d66') // dna
// this.loadPdbid('9dna') // A form dna
this.loadPdbid('1bna') // B form dna
// this.loadPdbid('1bna') // B form dna
// this.loadPdbid('199d') // C form dna
// this.loadPdbid('4lb6') // Z form dna
// this.loadPdbid('1egk') // 4-way dna-rna junction
......@@ -91,7 +91,7 @@ export class Stage {
// this.loadPdbid('1xv6') // rna, modified nucleotides
// this.loadPdbid('3bbm') // rna with linker
// this.loadPdbid('1gfl') // GFP, flourophore has carbonyl oxygen removed
// this.loadPdbid('1sfi') // contains cyclic peptid
this.loadPdbid('1sfi') // contains cyclic peptid
// this.loadPdbid('3sn6') // discontinuous chains
// this.loadMmcifUrl(`../../examples/1cbs_full.bcif`)
// this.loadMmcifUrl(`../../examples/1cbs_updated.cif`)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment