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

add support for Beta and Gamma peptides

parent 96a90869
Branches
Tags
No related merge requests found
Showing
with 144 additions and 64 deletions
......@@ -30,7 +30,7 @@ export class EntityBuilder {
}
getEntityId(compId: string, moleculeType: MoleculeType, chainId: string): string {
if (moleculeType === MoleculeType.water) {
if (moleculeType === MoleculeType.Water) {
if (this.waterId === undefined) {
this.set('water', 'Water')
this.waterId = `${this.count}`
......
......@@ -36,7 +36,7 @@ function getCategories(atoms: GroAtoms) {
let currentAsymIndex = 0
let currentAsymId = ''
let currentSeqId = 0
let prevMoleculeType = MoleculeType.unknown
let prevMoleculeType = MoleculeType.Unknown
let prevResidueNumber = -1
for (let i = 0, il = atoms.count; i < il; ++i) {
......
......@@ -180,7 +180,7 @@ function getSaccharideComponentMap(format: mmCIF_Format): SaccharideComponentMap
const _type = type.value(i)
if (SaccharideCompIdMap.has(_id)) {
map.set(_id, SaccharideCompIdMap.get(_id)!)
} else if (getMoleculeType(_type, _id) === MoleculeType.saccharide) {
} else if (getMoleculeType(_type, _id) === MoleculeType.Saccharide) {
map.set(_id, UnknownSaccharideComponent)
}
}
......
......@@ -8,7 +8,7 @@
import { Column, Table } from '../../../../../mol-data/db'
import { Segmentation } from '../../../../../mol-data/int'
import { mmCIF_Schema as mmCIF } from '../../../../../mol-io/reader/cif/schema/mmcif'
import { ElementSymbol, MoleculeType } from '../../types'
import { ElementSymbol, MoleculeType, PolymerType } from '../../types'
import { ChainIndex, EntityIndex, ResidueIndex, ElementIndex } from '../../indexing';
import SortedRanges from '../../../../../mol-data/int/sorted-ranges';
......@@ -116,6 +116,7 @@ export interface AtomicDerivedData {
readonly directionFromElementIndex: ArrayLike<ElementIndex | -1>
readonly directionToElementIndex: ArrayLike<ElementIndex | -1>
readonly moleculeType: ArrayLike<MoleculeType>
readonly polymerType: ArrayLike<PolymerType>
}
}
......
......@@ -7,9 +7,10 @@
import { AtomicData } from '../atomic';
import { AtomicIndex, AtomicDerivedData } from '../atomic/hierarchy';
import { ElementIndex, ResidueIndex } from '../../indexing';
import { MoleculeType, getMoleculeType, getComponentType } from '../../types';
import { MoleculeType, getMoleculeType, getComponentType, PolymerType, getPolymerType } from '../../types';
import { getAtomIdForAtomRole } from '../../../../../mol-model/structure/util';
import { ChemicalComponentMap } from '../common';
import { isProductionMode } from '../../../../../mol-util/debug';
export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemicalComponentMap: ChemicalComponentMap): AtomicDerivedData {
const { label_comp_id, _rowCount: n } = data.residues
......@@ -18,38 +19,49 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi
const directionFromElementIndex = new Int32Array(n)
const directionToElementIndex = new Int32Array(n)
const moleculeType = new Uint8Array(n)
const polymerType = new Uint8Array(n)
const moleculeTypeMap = new Map<string, MoleculeType>()
const polymerTypeMap = new Map<string, PolymerType>()
for (let i = 0 as ResidueIndex; i < n; ++i) {
const compId = label_comp_id.value(i)
const chemCompMap = chemicalComponentMap
let molType: MoleculeType
let polyType: PolymerType
if (moleculeTypeMap.has(compId)) {
molType = moleculeTypeMap.get(compId)!
} else if (chemCompMap.has(compId)) {
molType = getMoleculeType(chemCompMap.get(compId)!.type, compId)
moleculeTypeMap.set(compId, molType)
polyType = polymerTypeMap.get(compId)!
} else {
console.log('chemComp not found', compId)
molType = getMoleculeType(getComponentType(compId), compId)
let type: string
if (chemCompMap.has(compId)) {
type = chemCompMap.get(compId)!.type
} else {
if (!isProductionMode) console.info('chemComp not found', compId)
type = getComponentType(compId)
}
molType = getMoleculeType(type, compId)
// TODO if unknown molecule type, use atom names to guess molecule type
polyType = getPolymerType(type, molType)
moleculeTypeMap.set(compId, molType)
polymerTypeMap.set(compId, polyType)
}
moleculeType[i] = molType
polymerType[i] = polyType
const traceAtomId = getAtomIdForAtomRole(molType, 'trace')
const traceAtomId = getAtomIdForAtomRole(polyType, 'trace')
let traceIndex = index.findAtomsOnResidue(i, traceAtomId)
if (traceIndex === -1) {
const coarseAtomId = getAtomIdForAtomRole(molType, 'coarseBackbone')
const coarseAtomId = getAtomIdForAtomRole(polyType, 'coarseBackbone')
traceIndex = index.findAtomsOnResidue(i, coarseAtomId)
}
traceElementIndex[i] = traceIndex
const directionFromAtomId = getAtomIdForAtomRole(molType, 'directionFrom')
const directionFromAtomId = getAtomIdForAtomRole(polyType, 'directionFrom')
directionFromElementIndex[i] = index.findAtomsOnResidue(i, directionFromAtomId)
const directionToAtomId = getAtomIdForAtomRole(molType, 'directionTo')
const directionToAtomId = getAtomIdForAtomRole(polyType, 'directionTo')
directionToElementIndex[i] = index.findAtomsOnResidue(i, directionToAtomId)
}
......@@ -59,6 +71,7 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi
directionFromElementIndex: directionFromElementIndex as unknown as ArrayLike<ElementIndex | -1>,
directionToElementIndex: directionToElementIndex as unknown as ArrayLike<ElementIndex | -1>,
moleculeType: moleculeType as unknown as ArrayLike<MoleculeType>,
polymerType: polymerType as unknown as ArrayLike<PolymerType>,
}
}
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
import { AtomicRanges, AtomicIndex, AtomicHierarchy, AtomicDerivedData } from '../atomic/hierarchy';
import { Segmentation, Interval } from '../../../../../mol-data/int';
import SortedRanges from '../../../../../mol-data/int/sorted-ranges';
import { isPolymer } from '../../types';
import { isPolymer, PolymerType } from '../../types';
import { ElementIndex, ResidueIndex } from '../../indexing';
import { getAtomIdForAtomRole } from '../../../util';
import { AtomicConformation } from '../atomic/conformation';
......@@ -16,18 +16,18 @@ import { Entities } from '../common';
import StructureSequence from '../sequence';
function areBackboneConnected(riStart: ResidueIndex, riEnd: ResidueIndex, conformation: AtomicConformation, index: AtomicIndex, derived: AtomicDerivedData) {
const { moleculeType, traceElementIndex, directionFromElementIndex, directionToElementIndex } = derived.residue
const mtStart = moleculeType[riStart]
const mtEnd = moleculeType[riEnd]
if (!isPolymer(mtStart) || !isPolymer(mtEnd)) return false
const { polymerType, traceElementIndex, directionFromElementIndex, directionToElementIndex } = derived.residue
const ptStart = polymerType[riStart]
const ptEnd = polymerType[riEnd]
if (ptStart === PolymerType.NA || ptEnd === PolymerType.NA) return false
if (traceElementIndex[riStart] === -1 || traceElementIndex[riEnd] === -1) return false
let eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(mtStart, 'backboneStart'))
let eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(mtEnd, 'backboneEnd'))
let eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(ptStart, 'backboneStart'))
let eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(ptEnd, 'backboneEnd'))
if (eiStart === -1 || eiEnd === -1) {
eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(mtStart, 'coarseBackbone'))
eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(mtEnd, 'coarseBackbone'))
eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(ptStart, 'coarseBackbone'))
eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(ptEnd, 'coarseBackbone'))
}
const { x, y, z } = conformation
......
......@@ -40,30 +40,49 @@ export const enum EntityType {
}
export const enum MoleculeType {
/** the molecule type is not known */
unknown,
/** a known, but here not listed molecule type */
other,
/** water molecule */
water,
/** small ionic molecule */
ion,
/** protein, e.g. component type included in `ProteinComponentTypeNames` */
protein,
/** The molecule type is not known */
Unknown,
/** A known, but here not listed molecule type */
Other,
/** Water molecule */
Water,
/** Small ionic molecule */
Ion,
/** Protein, e.g. component type included in `ProteinComponentTypeNames` */
Protein,
/** RNA, e.g. component type included in `RNAComponentTypeNames` */
RNA,
/** DNA, e.g. component type included in `DNAComponentTypeNames` */
DNA,
/** PNA, peptide nucleic acid, comp id included in `PeptideBaseNames` */
PNA,
/** sacharide, e.g. component type included in `SaccharideComponentTypeNames` */
saccharide
/** Saccharide, e.g. component type included in `SaccharideComponentTypeNames` */
Saccharide
}
export const enum PolymerType {
/** not applicable */
NA,
Protein,
GammaProtein,
BetaProtein,
RNA,
DNA,
PNA,
}
export type AtomRole = 'trace' | 'directionFrom' | 'directionTo' | 'backboneStart' | 'backboneEnd' | 'coarseBackbone'
export const MoleculeTypeAtomRoleId: { [k: number]: { [k in AtomRole]: Set<string> } } = {
[MoleculeType.protein]: {
export const PolymerTypeAtomRoleId: { [k in PolymerType]: { [k in AtomRole]: Set<string> } } = {
[PolymerType.NA]: {
trace: new Set(),
directionFrom: new Set(),
directionTo: new Set(),
backboneStart: new Set(),
backboneEnd: new Set(),
coarseBackbone: new Set()
},
[PolymerType.Protein]: {
trace: new Set(['CA']),
directionFrom: new Set(['C']),
directionTo: new Set(['O', 'OC1', 'O1', 'OX1', 'OXT']),
......@@ -73,7 +92,23 @@ export const MoleculeTypeAtomRoleId: { [k: number]: { [k in AtomRole]: Set<strin
// BB is often used for coarse grained models
coarseBackbone: new Set(['CA', 'BB', 'CA1'])
},
[MoleculeType.RNA]: {
[PolymerType.GammaProtein]: {
trace: new Set(['CA']),
directionFrom: new Set(['C']),
directionTo: new Set(['O']),
backboneStart: new Set(['N']),
backboneEnd: new Set(['CD']),
coarseBackbone: new Set(['CA'])
},
[PolymerType.BetaProtein]: {
trace: new Set(['CA']),
directionFrom: new Set(['C']),
directionTo: new Set(['O']),
backboneStart: new Set(['N']),
backboneEnd: new Set(['CG']),
coarseBackbone: new Set(['CA'])
},
[PolymerType.RNA]: {
trace: new Set(['C4\'', 'C4*']),
directionFrom: new Set(['C4\'', 'C4*']),
directionTo: new Set(['C3\'', 'C3*']),
......@@ -81,7 +116,7 @@ export const MoleculeTypeAtomRoleId: { [k: number]: { [k in AtomRole]: Set<strin
backboneEnd: new Set(['O3\'', 'O3*']),
coarseBackbone: new Set(['P'])
},
[MoleculeType.DNA]: {
[PolymerType.DNA]: {
trace: new Set(['C3\'', 'C3*']),
directionFrom: new Set(['C3\'', 'C3*']),
directionTo: new Set(['C1\'', 'C1*']),
......@@ -89,7 +124,7 @@ export const MoleculeTypeAtomRoleId: { [k: number]: { [k in AtomRole]: Set<strin
backboneEnd: new Set(['O3\'', 'O3*']),
coarseBackbone: new Set(['P'])
},
[MoleculeType.PNA]: {
[PolymerType.PNA]: {
trace: new Set(['N4\'', 'N4*']),
directionFrom: new Set(['N4\'', 'N4*']),
directionTo: new Set(['C7\'', 'C7*']),
......@@ -127,6 +162,16 @@ export const LProteinComponentTypeNames = new Set([
'L-BETA-PEPTIDE, C-GAMMA LINKING'
])
/** Chemical component type names for gamma protein, overlaps with D/L-linked */
export const GammaProteinComponentTypeNames = new Set([
'D-GAMMA-PEPTIDE, C-DELTA LINKING', 'L-GAMMA-PEPTIDE, C-DELTA LINKING'
])
/** Chemical component type names for beta protein, overlaps with D/L-linked */
export const BetaProteinComponentTypeNames = new Set([
'D-BETA-PEPTIDE, C-GAMMA LINKING', 'L-BETA-PEPTIDE, C-GAMMA LINKING'
])
/** Chemical component type names for pepdite-like protein */
export const OtherProteinComponentTypeNames = new Set([
'PEPTIDE LINKING', 'PEPTIDE-LIKE',
......@@ -206,32 +251,53 @@ export const isPyrimidineBase = (compId: string) => PyrimidineBaseNames.has(comp
export const PolymerNames = SetUtils.unionMany(AminoAcidNames, BaseNames)
/** get the molecule type from component type and id */
export function getMoleculeType(compType: string, compId: string) {
export function getMoleculeType(compType: string, compId: string): MoleculeType {
compType = compType.toUpperCase()
compId = compId.toUpperCase()
if (PeptideBaseNames.has(compId)) {
return MoleculeType.PNA
} else if (ProteinComponentTypeNames.has(compType)) {
return MoleculeType.protein
return MoleculeType.Protein
} else if (RNAComponentTypeNames.has(compType)) {
return MoleculeType.RNA
} else if (DNAComponentTypeNames.has(compType)) {
return MoleculeType.DNA
} else if (SaccharideComponentTypeNames.has(compType)) {
return MoleculeType.saccharide
return MoleculeType.Saccharide
} else if (WaterNames.has(compId)) {
return MoleculeType.water
return MoleculeType.Water
} else if (IonNames.has(compId)) {
return MoleculeType.ion
return MoleculeType.Ion
} else if (OtherComponentTypeNames.has(compType)) {
if (SaccharideCompIdMap.has(compId)) {
// trust our saccharide table more than given 'non-polymer' or 'other' component type
return MoleculeType.saccharide
return MoleculeType.Saccharide
} else {
return MoleculeType.other
return MoleculeType.Other
}
} else {
return MoleculeType.unknown
return MoleculeType.Unknown
}
}
export function getPolymerType(compType: string, molType: MoleculeType): PolymerType {
compType = compType.toUpperCase()
if (molType === MoleculeType.Protein) {
if (GammaProteinComponentTypeNames.has(compType)) {
return PolymerType.GammaProtein
} else if (BetaProteinComponentTypeNames.has(compType)) {
return PolymerType.BetaProtein
} else {
return PolymerType.Protein
}
} else if (molType === MoleculeType.RNA) {
return PolymerType.RNA
} else if (molType === MoleculeType.DNA) {
return PolymerType.DNA
} else if (molType === MoleculeType.PNA) {
return PolymerType.PNA
} else {
return PolymerType.NA
}
}
......@@ -316,7 +382,7 @@ export function isNucleic(moleculeType: MoleculeType) {
}
export function isProtein(moleculeType: MoleculeType) {
return moleculeType === MoleculeType.protein
return moleculeType === MoleculeType.Protein
}
/**
......
......@@ -192,7 +192,7 @@ namespace AccessibleSurfaceArea {
if (isNucleic(residueType)) {
ctx.atomRadius[aI] = determineRadiusNucl(atomId, element, compId);
} else if (residueType === MoleculeType.protein) {
} else if (residueType === MoleculeType.Protein) {
ctx.atomRadius[aI] = determineRadiusAmino(atomId, element, compId);
} else {
ctx.atomRadius[aI] = handleNonStandardCase(element);
......
......@@ -5,7 +5,7 @@
*/
import { Model, ResidueIndex, ElementIndex } from './model';
import { MoleculeType, AtomRole, MoleculeTypeAtomRoleId, getMoleculeType } from './model/types';
import { MoleculeType, AtomRole, PolymerTypeAtomRoleId, getMoleculeType, PolymerType } from './model/types';
import { Vec3 } from '../../mol-math/linear-algebra';
import { Unit } from './structure';
import Matrix from '../../mol-math/linear-algebra/matrix/matrix';
......@@ -28,7 +28,7 @@ export function getElementMoleculeType(unit: Unit, element: ElementIndex): Molec
const cc = unit.model.properties.chemicalComponentMap.get(compId)
if (cc) return getMoleculeType(cc.type, compId)
}
return MoleculeType.unknown
return MoleculeType.Unknown
}
export function getAtomicMoleculeType(model: Model, rI: ResidueIndex): MoleculeType {
......@@ -36,10 +36,10 @@ export function getAtomicMoleculeType(model: Model, rI: ResidueIndex): MoleculeT
}
const EmptyAtomIds = new Set<string>()
export function getAtomIdForAtomRole(moleculeType: MoleculeType, atomRole: AtomRole) {
const m = MoleculeTypeAtomRoleId[moleculeType]
if (m !== undefined) {
const a = m[atomRole]
export function getAtomIdForAtomRole(polymerType: PolymerType, atomRole: AtomRole) {
const p = PolymerTypeAtomRoleId[polymerType]
if (p !== undefined) {
const a = p[atomRole]
if (a !== undefined) return a
}
return EmptyAtomIds
......
......@@ -159,7 +159,7 @@ export const SceneLabels = PluginBehavior.create<SceneLabelsProps>({
if (p.levels.includes('ligand') && !u.polymerElements.length) {
const moleculeType = getElementMoleculeType(u, u.elements[0])
if (moleculeType === MoleculeType.other || moleculeType === MoleculeType.saccharide) {
if (moleculeType === MoleculeType.Other || moleculeType === MoleculeType.Saccharide) {
label = `${StructureProperties.entity.pdbx_description(l).join(', ')} (${getAsymId(u)(l)})`
}
}
......
......@@ -56,7 +56,7 @@ function createPolymerTraceElement (unit: Unit): PolymerTraceElement {
initial: false, final: false,
secStrucFirst: false, secStrucLast: false,
secStrucType: SecStrucTypeNA,
moleculeType: MoleculeType.unknown,
moleculeType: MoleculeType.Unknown,
coarseBackboneFirst: false, coarseBackboneLast: false,
isCoarseBackbone: false,
p0: Vec3(), p1: Vec3(), p2: Vec3(), p3: Vec3(), p4: Vec3(),
......
......@@ -41,13 +41,13 @@ export function getMoleculeTypeColorThemeParams(ctx: ThemeDataContext) {
export function moleculeTypeColor(colorMap: MoleculeTypeColors, unit: Unit, element: ElementIndex): Color {
const moleculeType = getElementMoleculeType(unit, element)
switch (moleculeType) {
case MoleculeType.water: return colorMap.water
case MoleculeType.ion: return colorMap.ion
case MoleculeType.protein: return colorMap.protein
case MoleculeType.Water: return colorMap.water
case MoleculeType.Ion: return colorMap.ion
case MoleculeType.Protein: return colorMap.protein
case MoleculeType.RNA: return colorMap.RNA
case MoleculeType.DNA: return colorMap.DNA
case MoleculeType.PNA: return colorMap.PNA
case MoleculeType.saccharide: return colorMap.saccharide
case MoleculeType.Saccharide: return colorMap.saccharide
}
return DefaultMoleculeTypeColor
}
......
......@@ -75,9 +75,9 @@ export function secondaryStructureColor(colorMap: SecondaryStructureColors, unit
return colorMap.dna
} else if (moleculeType === MoleculeType.RNA) {
return colorMap.rna
} else if (moleculeType === MoleculeType.saccharide) {
} else if (moleculeType === MoleculeType.Saccharide) {
return colorMap.carbohydrate
} else if (moleculeType === MoleculeType.protein) {
} else if (moleculeType === MoleculeType.Protein) {
return colorMap.coil
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment