molstar
Version:
A comprehensive macromolecular library.
173 lines (172 loc) • 7.44 kB
JavaScript
/**
* Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit, StructureElement, Structure } from '../../../../mol-model/structure';
import { EmptyLoci } from '../../../../mol-model/loci';
import { LocationIterator } from '../../../../mol-geo/util/location-iterator';
import { getResidueLoci } from './common';
import { eachAtomicUnitTracedElement } from './polymer';
import { isPurineBase, isPyrimidineBase } from '../../../../mol-model/structure/model/types';
import { Vec3 } from '../../../../mol-math/linear-algebra/3d/vec3';
export var NucleotideLocationIterator;
(function (NucleotideLocationIterator) {
function fromGroup(structureGroup) {
const { group, structure } = structureGroup;
const u = group.units[0];
const nucleotideElementIndices = Unit.isAtomic(u) ? u.nucleotideElements : [];
const groupCount = nucleotideElementIndices.length;
const instanceCount = group.units.length;
const location = StructureElement.Location.create(structure);
const getLocation = (groupIndex, instanceIndex) => {
const unit = group.units[instanceIndex];
location.unit = unit;
location.element = nucleotideElementIndices[groupIndex];
return location;
};
return LocationIterator(groupCount, instanceCount, 1, getLocation);
}
NucleotideLocationIterator.fromGroup = fromGroup;
})(NucleotideLocationIterator || (NucleotideLocationIterator = {}));
export function getNucleotideElementLoci(pickingId, structureGroup, id) {
const { objectId, instanceId, groupId } = pickingId;
if (id === objectId) {
const { structure, group } = structureGroup;
const unit = group.units[instanceId];
if (Unit.isAtomic(unit)) {
return getResidueLoci(structure, unit, unit.nucleotideElements[groupId]);
}
}
return EmptyLoci;
}
function selectNuclotideElements(u) { return u.nucleotideElements; }
/**
* 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, structureGroup, apply) {
let changed = false;
if (!StructureElement.Loci.is(loci))
return false;
const { structure, group } = structureGroup;
if (!Structure.areEquivalent(loci.structure, structure))
return false;
const unit = group.units[0];
if (!Unit.isAtomic(unit))
return false;
const { nucleotideElements } = unit;
const groupCount = nucleotideElements.length;
for (const e of loci.elements) {
if (!Unit.isAtomic(e.unit))
continue;
if (!group.unitIndexMap.has(e.unit.id))
continue;
const intervalOffset = group.unitIndexMap.get(e.unit.id) * groupCount;
if (Unit.isAtomic(e.unit)) {
changed = eachAtomicUnitTracedElement(intervalOffset, groupCount, selectNuclotideElements, apply, e) || changed;
}
}
return changed;
}
//
const pC4 = Vec3();
const pN9 = Vec3();
export function getNucleotideBaseType(unit, residueIndex) {
const { model, conformation: c } = unit;
const { residueAtomSegments, atoms, index: atomicIndex } = model.atomicHierarchy;
const { label_comp_id } = atoms;
const compId = label_comp_id.value(residueAtomSegments.offsets[residueIndex]);
let isPurine = isPurineBase(compId);
let isPyrimidine = isPyrimidineBase(compId);
if (!isPurine && !isPyrimidine) {
// detect Purine or Pyrimidin based on geometry
const idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4');
const idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9');
if (idxC4 !== -1 && idxN9 !== -1 && Vec3.distance(c.invariantPosition(idxC4, pC4), c.invariantPosition(idxN9, pN9)) < 1.6) {
isPurine = true;
}
else {
isPyrimidine = true;
}
}
return { isPurine, isPyrimidine };
}
export function createNucleicIndices() {
return {
trace: -1,
N1: -1,
C2: -1,
N3: -1,
C4: -1,
C5: -1,
C6: -1,
N7: -1,
C8: -1,
N9: -1,
C1_1: -1,
C2_1: -1,
C3_1: -1,
C4_1: -1,
O4_1: -1,
};
}
export function setPurinIndices(idx, unit, residueIndex) {
const atomicIndex = unit.model.atomicHierarchy.index;
const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue;
idx.trace = traceElementIndex[residueIndex];
idx.N1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1');
idx.C2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2');
idx.N3 = atomicIndex.findAtomOnResidue(residueIndex, 'N3');
idx.C4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4');
idx.C5 = atomicIndex.findAtomOnResidue(residueIndex, 'C5');
if (idx.C5 === -1) {
// modified ring, e.g. DP
idx.C5 = atomicIndex.findAtomOnResidue(residueIndex, 'N5');
}
idx.C6 = atomicIndex.findAtomOnResidue(residueIndex, 'C6');
idx.N7 = atomicIndex.findAtomOnResidue(residueIndex, 'N7');
if (idx.N7 === -1) {
// modified ring, e.g. DP
idx.N7 = atomicIndex.findAtomOnResidue(residueIndex, 'C7');
}
idx.C8 = atomicIndex.findAtomOnResidue(residueIndex, 'C8');
idx.N9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9');
return idx;
}
export function hasPurinIndices(idx) {
return idx.trace !== -1 && idx.N1 !== -1 && idx.C2 !== -1 && idx.N3 !== -1 && idx.C4 !== -1 && idx.C5 !== -1 && idx.C6 !== -1 && idx.N7 !== -1 && idx.C8 !== -1 && idx.N9 !== -1;
}
export function setPyrimidineIndices(idx, unit, residueIndex) {
const atomicIndex = unit.model.atomicHierarchy.index;
const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue;
idx.trace = traceElementIndex[residueIndex];
idx.N1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1');
if (idx.N1 === -1) {
// modified ring, e.g. DZ
idx.N1 = atomicIndex.findAtomOnResidue(residueIndex, 'C1');
}
idx.C2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2');
idx.N3 = atomicIndex.findAtomOnResidue(residueIndex, 'N3');
idx.C4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4');
idx.C5 = atomicIndex.findAtomOnResidue(residueIndex, 'C5');
idx.C6 = atomicIndex.findAtomOnResidue(residueIndex, 'C6');
return idx;
}
export function hasPyrimidineIndices(idx) {
return idx.trace !== -1 && idx.N1 !== -1 && idx.C2 !== -1 && idx.N3 !== -1 && idx.C4 !== -1 && idx.C5 !== -1 && idx.C6 !== -1;
}
export function setSugarIndices(idx, unit, residueIndex) {
const atomicIndex = unit.model.atomicHierarchy.index;
const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue;
idx.trace = traceElementIndex[residueIndex];
idx.C1_1 = atomicIndex.findAtomOnResidue(residueIndex, "C1'");
idx.C2_1 = atomicIndex.findAtomOnResidue(residueIndex, "C2'");
idx.C3_1 = atomicIndex.findAtomOnResidue(residueIndex, "C3'");
idx.C4_1 = atomicIndex.findAtomOnResidue(residueIndex, "C4'");
idx.O4_1 = atomicIndex.findAtomOnResidue(residueIndex, "O4'");
return idx;
}
export function hasSugarIndices(idx) {
return idx.trace !== -1 && idx.C1_1 !== -1 && idx.C2_1 !== -1 && idx.C3_1 !== -1 && idx.C4_1 !== -1 && idx.O4_1 !== -1;
}