diff --git a/src/mol-model/structure/model/types.ts b/src/mol-model/structure/model/types.ts index 1d48173bf56c23c33555852bf3ba4e43d33a2708..036fd11d0cab18c9d66591b80ae058ced91e8e1d 100644 --- a/src/mol-model/structure/model/types.ts +++ b/src/mol-model/structure/model/types.ts @@ -178,11 +178,11 @@ export const AminoAcidNames = new Set([ export const RnaBaseNames = new Set([ 'A', 'C', 'T', 'G', 'I', 'U' ]) export const DnaBaseNames = new Set([ 'DA', 'DC', 'DT', 'DG', 'DI', 'DU' ]) export const PeptideBaseNames = new Set([ 'APN', 'CPN', 'TPN', 'GPN' ]) -export const PurinBaseNames = new Set([ 'A', 'G', 'DA', 'DG', 'DI', 'APN', 'GPN' ]) +export const PurineBaseNames = new Set([ 'A', 'G', 'DA', 'DG', 'DI', 'APN', 'GPN' ]) export const PyrimidineBaseNames = new Set([ 'C', 'T', 'U', 'DC', 'DT', 'DU', 'CPN', 'TPN' ]) export const BaseNames = SetUtils.unionMany(RnaBaseNames, DnaBaseNames, PeptideBaseNames) -export const isPurinBase = (compId: string) => PurinBaseNames.has(compId.toUpperCase()) +export const isPurineBase = (compId: string) => PurineBaseNames.has(compId.toUpperCase()) export const isPyrimidineBase = (compId: string) => PyrimidineBaseNames.has(compId.toUpperCase()) /** get the molecule type from component type and id */ diff --git a/src/mol-repr/structure/visual/nucleotide-block-mesh.ts b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts index 885e01805c39cc7a2ec860e6d23035650b537729..36f7dc6f076269451db6c5f464ae5172a5df9463 100644 --- a/src/mol-repr/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts @@ -14,7 +14,7 @@ import { Mesh } from '../../../mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder'; import { Segmentation } from '../../../mol-data/int'; import { CylinderProps } from '../../../mol-geo/primitive/cylinder'; -import { isNucleic, isPurinBase, isPyrimidineBase } from '../../../mol-model/structure/model/types'; +import { isNucleic, isPurineBase, isPyrimidineBase } from '../../../mol-model/structure/model/types'; import { addCylinder } from '../../../mol-geo/geometry/mesh/builder/cylinder'; import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual } from '../units-visual'; import { NucleotideLocationIterator, getNucleotideElementLoci, eachNucleotideElement } from './util/nucleotide'; @@ -78,7 +78,21 @@ function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: St let idx1: ElementIndex | -1 = -1, idx2: ElementIndex | -1 = -1, idx3: ElementIndex | -1 = -1, idx4: ElementIndex | -1 = -1, idx5: ElementIndex | -1 = -1, idx6: ElementIndex | -1 = -1 let width = 4.5, height = 4.5, depth = 2.5 * sizeFactor - if (isPurinBase(compId)) { + 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(pos(idxC4, p1), pos(idxN9, p2)) < 1.6) { + isPurine = true + } else { + isPyrimidine = true + } + } + + if (isPurine) { height = 4.5 idx1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') idx2 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') @@ -86,7 +100,7 @@ function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: St idx4 = atomicIndex.findAtomOnResidue(residueIndex, 'C2') idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'N9') idx6 = traceElementIndex[residueIndex] - } else if (isPyrimidineBase(compId)) { + } else if (isPyrimidine) { height = 3.0 idx1 = atomicIndex.findAtomOnResidue(residueIndex, 'N3') idx2 = atomicIndex.findAtomOnResidue(residueIndex, 'C6') diff --git a/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts b/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts index 992b107cf2ee1e219370aee2d3f1b6c0fb20434f..8a1e820171c56fc2582b11f97a78e17171ce3962 100644 --- a/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts +++ b/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts @@ -14,7 +14,7 @@ import { Mesh } from '../../../mol-geo/geometry/mesh/mesh'; import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder'; import { Segmentation } from '../../../mol-data/int'; import { CylinderProps } from '../../../mol-geo/primitive/cylinder'; -import { isNucleic, isPurinBase, isPyrimidineBase } from '../../../mol-model/structure/model/types'; +import { isNucleic, isPurineBase, isPyrimidineBase } from '../../../mol-model/structure/model/types'; import { addCylinder } from '../../../mol-geo/geometry/mesh/builder/cylinder'; import { addSphere } from '../../../mol-geo/geometry/mesh/builder/sphere'; import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual } from '../units-visual'; @@ -101,7 +101,21 @@ function createNucleotideRingMesh(ctx: VisualContext, unit: Unit, structure: Str builderState.currentGroup = i - if (isPurinBase(compId)) { + 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(pos(idxC4, pC4), pos(idxN9, pN9)) < 1.6) { + isPurine = true + } else { + isPyrimidine = true + } + } + + if (isPurine) { idxTrace = traceElementIndex[residueIndex] idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') idxC2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2') @@ -131,7 +145,7 @@ function createNucleotideRingMesh(ctx: VisualContext, unit: Unit, structure: Str MeshBuilder.addTriangleFan(builderState, positionsRing5_6, fanIndicesTopRing5_6) MeshBuilder.addTriangleFan(builderState, positionsRing5_6, fanIndicesBottomRing5_6) } - } else if (isPyrimidineBase(compId)) { + } else if (isPyrimidine) { idxTrace = traceElementIndex[residueIndex] idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') idxC2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2')