Browse Source

chemComp refactoring

Alexander Rose 6 years ago
parent
commit
d9b566a58c

+ 5 - 16
src/mol-model-formats/structure/mmcif/parser.ts

@@ -23,8 +23,8 @@ import { getSecondaryStructureMmCif } from './secondary-structure';
 import { getSequence } from './sequence';
 import { sortAtomSite } from './sort';
 import { StructConn } from './bonds/struct_conn';
-import { ChemicalComponent, ChemicalComponentMap } from 'mol-model/structure/model/properties/chemical-component';
-import { ComponentType, getMoleculeType, MoleculeType } from 'mol-model/structure/model/types';
+import { ChemicalComponent } from 'mol-model/structure/model/properties/chemical-component';
+import { getMoleculeType, MoleculeType } from 'mol-model/structure/model/types';
 import { ModelFormat } from '../format';
 import { SaccharideComponentMap, SaccharideComponent, SaccharidesSnfgMap, SaccharideCompIdMap, UnknownSaccharideComponent } from 'mol-model/structure/structure/carbohydrates/constants';
 import mmCIF_Format = ModelFormat.mmCIF
@@ -96,24 +96,13 @@ function getModifiedResidueNameMap(format: mmCIF_Format): Model['properties']['m
     return { parentId, details };
 }
 
-function getChemicalComponentMap(format: mmCIF_Format): ChemicalComponentMap {
+function getChemicalComponentMap(format: mmCIF_Format): Model['properties']['chemicalComponentMap'] {
     const map = new Map<string, ChemicalComponent>();
     const { chem_comp } = format.data
     if (chem_comp._rowCount > 0) {
-        const { id, type, name, pdbx_synonyms, formula, formula_weight } = format.data.chem_comp
+        const { id } = format.data.chem_comp
         for (let i = 0, il = id.rowCount; i < il; ++i) {
-            const _id = id.value(i)
-            const _type = type.value(i)
-            const cc: ChemicalComponent = {
-                id: _id,
-                type: ComponentType[_type],
-                moleculeType: getMoleculeType(_type, _id),
-                name: name.value(i),
-                synonyms: pdbx_synonyms.value(i),
-                formula: formula.value(i),
-                formulaWeight: formula_weight.value(i),
-            }
-            map.set(_id, cc)
+            map.set(id.value(i), Table.getRow(format.data.chem_comp, i))
         }
     }
     return map

+ 1 - 1
src/mol-model/structure/model/model.ts

@@ -12,9 +12,9 @@ import { CoarseHierarchy, CoarseConformation } from './properties/coarse';
 import { Entities } from './properties/common';
 import { CustomProperties } from './properties/custom';
 import { SecondaryStructure } from './properties/seconday-structure';
-import { ChemicalComponentMap } from './properties/chemical-component';
 import { SaccharideComponentMap } from '../structure/carbohydrates/constants';
 import { ModelFormat } from 'mol-model-formats/structure/format';
+import { ChemicalComponentMap } from './properties/chemical-component';
 
 /**
  * Interface to the "source data" of the molecule.

+ 5 - 11
src/mol-model/structure/model/properties/chemical-component.ts

@@ -4,16 +4,10 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { MoleculeType, ComponentType } from '../types'
+import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif';
+import { Table } from 'mol-data/db';
 
-export interface ChemicalComponent {
-    id: string
-    type: ComponentType
-    moleculeType: MoleculeType
-    name: string
-    synonyms: string[]
-    formula: string
-    formulaWeight: number
-}
+export type ChemicalComponent = Table.Row<mmCIF_Schema['chem_comp']>
+export type ChemicalComponentMap = ReadonlyMap<string, ChemicalComponent>
 
-export type ChemicalComponentMap = ReadonlyMap<string, ChemicalComponent>
+// TODO add data for common chemical components

+ 4 - 4
src/mol-model/structure/model/properties/utils/atomic-derived.ts

@@ -23,12 +23,12 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi
     for (let i = 0; i < n; ++i) {
         const compId = label_comp_id.value(i)
         const chemCompMap = chemicalComponentMap
-        const cc = chemCompMap.get(compId)
         let molType: MoleculeType
-        if (cc) {
-            molType = cc.moleculeType
-        } else if (moleculeTypeMap.has(compId)){
+        if (moleculeTypeMap.has(compId)){
             molType = moleculeTypeMap.get(compId)!
+        } else if (chemCompMap.has(compId)) {
+            molType = getMoleculeType(chemCompMap.get(compId)!.type, compId)
+            moleculeTypeMap.set(compId, molType)
         } else {
             molType = getMoleculeType(getComponentType(compId), compId)
             // TODO if unknown molecule type, use atom names to guess molecule type

+ 5 - 25
src/mol-model/structure/model/types.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -7,6 +7,7 @@
 
 import BitFlags from 'mol-util/bit-flags'
 import { SaccharideCompIdMap } from '../structure/carbohydrates/constants';
+import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif';
 
 const _esCache = (function () {
     const cache = Object.create(null);
@@ -100,29 +101,6 @@ export const NucleicBackboneAtoms = [
     'O2*', 'O3*', 'O4*', 'O5*', 'C1*', 'C2*', 'C3*', 'C4*', 'C5*'
 ]
 
-/** Chemical component types as defined in the mmCIF CCD */
-export enum ComponentType {
-    // protein
-    'D-peptide linking', 'L-peptide linking', 'D-peptide NH3 amino terminus',
-    'L-peptide NH3 amino terminus', 'D-peptide COOH carboxy terminus',
-    'L-peptide COOH carboxy terminus', 'peptide linking', 'peptide-like',
-    'L-gamma-peptide, C-delta linking', 'D-gamma-peptide, C-delta linking',
-    'L-beta-peptide, C-gamma linking', 'D-beta-peptide, C-gamma linking',
-
-    // DNA
-    'DNA linking', 'L-DNA linking', 'DNA OH 5 prime terminus', 'DNA OH 3 prime terminus',
-
-    // RNA
-    'RNA linking', 'L-RNA linking', 'RNA OH 5 prime terminus', 'RNA OH 3 prime terminus',
-
-    // sacharide
-    'D-saccharide 1,4 and 1,4 linking', 'L-saccharide 1,4 and 1,4 linking',
-    'D-saccharide 1,4 and 1,6 linking', 'L-saccharide 1,4 and 1,6 linking', 'L-saccharide',
-    'D-saccharide', 'saccharide',
-
-    'non-polymer', 'other'
-}
-
 /** Chemical component type names for protein */
 export const ProteinComponentTypeNames = [
     'D-PEPTIDE LINKING', 'L-PEPTIDE LINKING', 'D-PEPTIDE NH3 AMINO TERMINUS',
@@ -221,7 +199,7 @@ export function getMoleculeType(compType: string, compId: string) {
     }
 }
 
-export function getComponentType(compId: string) {
+export function getComponentType(compId: string): mmCIF_Schema['chem_comp']['type']['T'] {
     compId = compId.toUpperCase()
     if (AminoAcidNames.includes(compId)) {
         return 'peptide linking'
@@ -245,6 +223,8 @@ export function isNucleic(moleculeType: MoleculeType) {
 }
 
 /**
+ * TODO write script that read CCD and outputs list of ion names
+ * 
  * all chemical components with the word "ion" in their name, Sep 2016
  *
  * SET SESSION group_concat_max_len = 1000000;

+ 11 - 16
src/mol-model/structure/util.ts

@@ -1,11 +1,11 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 import { Model, ResidueIndex, ElementIndex } from './model';
-import { MoleculeType, AtomRole, MoleculeTypeAtomRoleId } from './model/types';
+import { MoleculeType, AtomRole, MoleculeTypeAtomRoleId, getMoleculeType } from './model/types';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Unit } from './structure';
 import Matrix from 'mol-math/linear-algebra/matrix/matrix';
@@ -17,27 +17,22 @@ export function getCoarseBegCompId(unit: Unit.Spheres | Unit.Gaussians, element:
     return seq.compId.value(seq_id_begin - 1) // 1-indexed
 }
 
-export function getElementMoleculeType(unit: Unit, element: ElementIndex) {
-    let compId = ''
+export function getElementMoleculeType(unit: Unit, element: ElementIndex): MoleculeType {
     switch (unit.kind) {
         case Unit.Kind.Atomic:
-            compId = unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element])
-            break
+            return unit.model.atomicHierarchy.derived.residue.moleculeType[unit.residueIndex[element]]
         case Unit.Kind.Spheres:
         case Unit.Kind.Gaussians:
-            compId = getCoarseBegCompId(unit, element)
-            break
+            // TODO add unit.model.coarseHierarchy.derived.residue.moleculeType
+            const compId = getCoarseBegCompId(unit, element)
+            const cc = unit.model.properties.chemicalComponentMap.get(compId)
+            if (cc) return getMoleculeType(cc.type, compId)
     }
-    const chemCompMap = unit.model.properties.chemicalComponentMap
-    const cc = chemCompMap.get(compId)
-    return cc ? cc.moleculeType : MoleculeType.unknown
+    return MoleculeType.unknown
 }
 
-export function getAtomicMoleculeType(model: Model, rI: ResidueIndex) {
-    const compId = model.atomicHierarchy.residues.label_comp_id.value(rI)
-    const chemCompMap = model.properties.chemicalComponentMap
-    const cc = chemCompMap.get(compId)
-    return cc ? cc.moleculeType : MoleculeType.unknown
+export function getAtomicMoleculeType(model: Model, rI: ResidueIndex): MoleculeType {
+    return model.atomicHierarchy.derived.residue.moleculeType[rI]
 }
 
 export function getAtomIdForAtomRole(moleculeType: MoleculeType, atomRole: AtomRole) {

+ 2 - 3
src/mol-plugin/behavior/dynamic/labels.ts

@@ -21,6 +21,7 @@ import { Unit, StructureElement, StructureProperties } from 'mol-model/structure
 import { SetUtils } from 'mol-util/set';
 import { arrayEqual } from 'mol-util';
 import { MoleculeType } from 'mol-model/structure/model/types';
+import { getElementMoleculeType } from 'mol-model/structure/util';
 
 // TODO
 // - support more object types than structures
@@ -157,9 +158,7 @@ export const SceneLabels = PluginBehavior.create<SceneLabelsProps>({
                     }
 
                     if (p.levels.includes('ligand') && !u.polymerElements.length) {
-                        const compId = StructureProperties.residue.label_comp_id(l)
-                        const chemComp = u.model.properties.chemicalComponentMap.get(compId)
-                        const moleculeType = chemComp ? chemComp.moleculeType : MoleculeType.unknown
+                        const moleculeType = getElementMoleculeType(u, u.elements[0])
                         if (moleculeType === MoleculeType.other || moleculeType === MoleculeType.saccharide) {
                             label = `${StructureProperties.entity.pdbx_description(l).join(', ')} (${getAsymId(u)(l)})`
                         }