Browse Source

Model.entities is now a standalone property, updated CoraseGrained,

David Sehnal 7 years ago
parent
commit
57f1aa51f3

+ 1 - 1
src/apps/domain-annotation-server/mapping.ts

@@ -112,6 +112,6 @@ function getDomain(name: string, schema: any, allData: any) {
     return domains.length > 0 ? {
         name,
         domains: Table.ofRows({ ...S.Base, ...schema }, domains),
-        mappings: Table.ofRows(S.mapping, mappings)
+        mappings: Table.ofRows<S.mapping>(S.mapping, mappings)
     } : void 0;
 }

+ 13 - 0
src/mol-data/db/column.ts

@@ -132,6 +132,10 @@ namespace Column {
         return createFirstIndexMapOfColumn(column);
     }
 
+    export function createIndexer<T>(column: Column<T>) {
+        return createIndexerOfColumn(column);
+    }
+
     export function mapToArray<T, S>(column: Column<T>, f: (v: T) => S, ctor?: ArrayCtor<S>): ArrayLike<S> {
         return mapToArrayImpl<T, S>(column, f, ctor || Array);
     }
@@ -174,6 +178,15 @@ function createFirstIndexMapOfColumn<T>(c: Column<T>): Map<T, number> {
     return map;
 }
 
+function createIndexerOfColumn<T>(c: Column<T>): (value: T) => number {
+    const map = new Map<T, number>();
+    for (let i = 0, _i = c.rowCount; i < _i; i++) {
+        const v = c.value(i);
+        if (!map.has(v)) map.set(c.value(i), i);
+    }
+    return v => map.has(v) ? map.get(v)! : -1;
+}
+
 function constColumn<T extends Column.Schema>(v: T['T'], rowCount: number, schema: T, valueKind: Column.ValueKind): Column<T['T']> {
     const value: Column<T['T']>['value'] = row => v;
     return {

+ 2 - 2
src/mol-data/db/table.ts

@@ -58,7 +58,7 @@ namespace Table {
         return ret;
     }
 
-    export function ofRows<S extends Schema, R extends Table<S> = Table<S>>(schema: Schema, rows: ArrayLike<Row<S>>): R {
+    export function ofRows<S extends Schema, R extends Table<S> = Table<S>>(schema: Schema, rows: ArrayLike<Partial<Row<S>>>): R {
         const ret = Object.create(null);
         const rowCount = rows.length;
         const columns = Object.keys(schema);
@@ -83,7 +83,7 @@ namespace Table {
         ret._columns = columns;
         ret._schema = schema;
         for (const k of columns) {
-            (ret as any)[k] = Column.ofArray({ array: arrays[k], schema: schema[k] })
+            (ret as any)[k] = typeof arrays[k] !== 'undefined' ? Column.ofArray({ array: arrays[k], schema: schema[k] }) : Column.Undefined(ret._rowCount, schema[k]);
         }
         return ret as R;
     }

+ 4 - 4
src/mol-model/structure/export/mmcif.ts

@@ -102,10 +102,10 @@ const atom_site: Encoder.CategoryDefinition<Element.Location> = {
 
 function entityProvider({ model }: Context): Encoder.CategoryInstance {
     return {
-        data: model.hierarchy.entities,
-        definition: Encoder.CategoryDefinition.ofTable('entity', model.hierarchy.entities),
-        keys: () => Iterator.Range(0, model.hierarchy.entities._rowCount - 1),
-        rowCount: model.hierarchy.entities._rowCount
+        data: model.entities.data,
+        definition: Encoder.CategoryDefinition.ofTable('entity', model.entities.data),
+        keys: () => Iterator.Range(0, model.entities.data._rowCount - 1),
+        rowCount: model.entities.data._rowCount
     }
 }
 

+ 16 - 3
src/mol-model/structure/model/formats/gro.ts

@@ -16,9 +16,11 @@ import CoarseGrained from '../properties/coarse-grained'
 import findHierarchyKeys from '../utils/hierarchy-keys'
 import { guessElement } from '../utils/guess-element'
 import { ElementSymbol} from '../types'
+import { mmCIF_Schema as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
 
 import gro_Format = Format.gro
 import Sequence from '../properties/sequence';
+import { Entities } from '../properties/common';
 
 type HierarchyOffsets = { residues: ArrayLike<number>, chains: ArrayLike<number> }
 
@@ -71,9 +73,8 @@ function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): Hiera
     // });
 
     const chains = Table.ofUndefinedColumns(Hierarchy.ChainsSchema, 0);
-    const entities = Table.ofUndefinedColumns(Hierarchy.EntitySchema, 0);
 
-    return { atoms, residues, chains, entities };
+    return { atoms, residues, chains };
 }
 
 function getConformation(atoms: Atoms): Conformation {
@@ -112,13 +113,25 @@ function createModel(format: gro_Format, modelNum: number, previous?: Model): Mo
         residueSegments: Segmentation.ofOffsets(hierarchyOffsets.residues, bounds),
         chainSegments: Segmentation.ofOffsets(hierarchyOffsets.chains, bounds),
     }
-    const hierarchyKeys = findHierarchyKeys(hierarchyData, hierarchySegments);
+
+    // TODO: create a better mock entity
+    const entityTable = Table.ofRows<mmCIF['entity']>(mmCIF.entity, [{
+        id: '0',
+        src_method: 'syn',
+        type: 'polymer',
+        pdbx_number_of_molecules: 1
+    }]);
+
+    const entities: Entities = { data: entityTable, getEntityIndex: Column.createIndexer(entityTable.id) };
+
+    const hierarchyKeys = findHierarchyKeys(hierarchyData, entities, hierarchySegments);
     const hierarchy = { ...hierarchyData, ...hierarchyKeys, ...hierarchySegments };
     return {
         id: UUID.create(),
         sourceData: format,
         modelNum,
         hierarchy,
+        entities,
         sequence: Sequence.fromHierarchy(hierarchy),
         conformation: getConformation(structure.atoms),
         coarseGrained: CoarseGrained.Empty,

+ 8 - 3
src/mol-model/structure/model/formats/mmcif.ts

@@ -19,6 +19,7 @@ import createAssemblies from './mmcif/assembly'
 
 import mmCIF_Format = Format.mmCIF
 import { getSequence } from './mmcif/sequence';
+import { Entities } from '../properties/common';
 
 function findModelBounds({ data }: mmCIF_Format, startIndex: number) {
     const num = data.atom_site.pdbx_PDB_model_num;
@@ -63,7 +64,7 @@ function createHierarchyData({ data }: mmCIF_Format, bounds: Interval, offsets:
     Table.columnToArray(residues, 'label_seq_id', Int32Array);
     Table.columnToArray(residues, 'auth_seq_id', Int32Array);
     const chains = Table.view(atom_site, Hierarchy.ChainsSchema, offsets.chains);
-    return { atoms, residues, chains, entities: data.entity };
+    return { atoms, residues, chains };
 }
 
 function getConformation({ data }: mmCIF_Format, bounds: Interval): Conformation {
@@ -106,7 +107,10 @@ function createModel(format: mmCIF_Format, bounds: Interval, previous?: Model):
         residueSegments: Segmentation.ofOffsets(hierarchyOffsets.residues, bounds),
         chainSegments: Segmentation.ofOffsets(hierarchyOffsets.chains, bounds),
     }
-    const hierarchyKeys = findHierarchyKeys(hierarchyData, hierarchySegments);
+
+    const entities: Entities = { data: format.data.entity, getEntityIndex: Column.createIndexer(format.data.entity.id) };
+
+    const hierarchyKeys = findHierarchyKeys(hierarchyData, entities, hierarchySegments);
 
     const hierarchy = { ...hierarchyData, ...hierarchyKeys, ...hierarchySegments };
 
@@ -114,8 +118,9 @@ function createModel(format: mmCIF_Format, bounds: Interval, previous?: Model):
         id: UUID.create(),
         sourceData: format,
         modelNum: format.data.atom_site.pdbx_PDB_model_num.value(Interval.start(bounds)),
+        entities,
         hierarchy,
-        sequence: getSequence(format.data, hierarchy),
+        sequence: getSequence(format.data, entities, hierarchy),
         conformation: getConformation(format, bounds),
         coarseGrained: CoarseGrained.Empty,
         symmetry: getSymmetry(format),

+ 6 - 0
src/mol-model/structure/model/formats/mmcif/ihm.ts

@@ -0,0 +1,6 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+

+ 3 - 2
src/mol-model/structure/model/formats/mmcif/sequence.ts

@@ -8,8 +8,9 @@ import { mmCIF_Database as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
 import Sequence from '../../properties/sequence'
 import { Column } from 'mol-data/db';
 import { Hierarchy } from '../../properties/hierarchy';
+import { Entities } from '../../properties/common';
 
-export function getSequence(cif: mmCIF, hierarchy: Hierarchy): Sequence {
+export function getSequence(cif: mmCIF, entities: Entities, hierarchy: Hierarchy): Sequence {
     if (!cif.entity_poly_seq._rowCount) return Sequence.fromHierarchy(hierarchy);
 
     const { entity_id, num, mon_id } = cif.entity_poly_seq;
@@ -24,7 +25,7 @@ export function getSequence(cif: mmCIF, hierarchy: Hierarchy): Sequence {
         i++;
 
         const id = entity_id.value(start);
-        byEntityKey[hierarchy.findEntityKey(id)] = { entityId: id, compId: Column.window(mon_id, start, i), num: Column.window(num, start, i)  }
+        byEntityKey[entities.getEntityIndex(id)] = { entityId: id, compId: Column.window(mon_id, start, i), num: Column.window(num, start, i)  }
     }
 
     return { byEntityKey };

+ 3 - 0
src/mol-model/structure/model/model.ts

@@ -11,6 +11,7 @@ import Hierarchy from './properties/hierarchy'
 import Conformation from './properties/conformation'
 import Symmetry from './properties/symmetry'
 import CoarseGrained from './properties/coarse-grained'
+import { Entities } from './properties/common';
 
 import from_gro from './formats/gro'
 import from_mmCIF from './formats/mmcif'
@@ -27,7 +28,9 @@ interface Model extends Readonly<{
 
     sourceData: Format,
 
+    entities: Entities,
     sequence: Sequence,
+
     hierarchy: Hierarchy,
     conformation: Conformation,
     symmetry: Symmetry,

+ 32 - 2
src/mol-model/structure/model/properties/coarse-grained.ts

@@ -4,12 +4,42 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
+import { mmCIF_Database as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
+import { Tensor } from 'mol-math/linear-algebra';
+import { Column } from 'mol-data/db';
+
 interface CoarseGrained {
-    // TODO
+    modelList: mmCIF['ihm_model_list'],
+    spheres: { [P in keyof CoarseGrained.Sphere]: Column<CoarseGrained.Sphere[P]> },
+    gaussians: { [P in keyof CoarseGrained.Gaussian]: Column<CoarseGrained.Gaussian[P]> }
 }
 
 namespace CoarseGrained {
-    export const Empty: CoarseGrained = { };
+    export const Empty: CoarseGrained = { } as any;
+
+    interface Site {
+        // index to the Model.hierarchy.entities table
+        entityKey: number,
+        // index to the CoarseGrained.modelList table
+        modelKey: number,
+
+        asym_id: string,
+        seq_id_begin: number,
+        seq_id_end: number,
+        x: number,
+        y: number,
+        z: number
+    }
+
+    export interface Sphere extends Site {
+        radius: number,
+        rmsf: number
+    }
+
+    export interface Gaussian extends Site {
+        weight: number,
+        covarianceMatrix: Tensor.Data
+    }
 }
 
 export default CoarseGrained;

+ 14 - 0
src/mol-model/structure/model/properties/common.ts

@@ -0,0 +1,14 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { mmCIF_Database as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
+
+interface Entities {
+    data: mmCIF['entity'],
+    getEntityIndex(id: string): number
+}
+
+export { Entities }

+ 4 - 5
src/mol-model/structure/model/properties/hierarchy.ts

@@ -40,15 +40,15 @@ export const ChainsSchema = {
 export type ChainsSchema = typeof ChainsSchema
 export interface Chains extends Table<ChainsSchema> { }
 
-export const EntitySchema = mmCIF['entity']
-export type EntitySchema = typeof EntitySchema
-export interface Entities extends Table<EntitySchema> { }
+// export const EntitySchema = mmCIF['entity']
+// export type EntitySchema = typeof EntitySchema
+// export interface Entities extends Table<EntitySchema> { }
 
 export interface Data {
     atoms: Atoms,
     residues: Residues,
     chains: Chains,
-    entities: Entities
+    //entities: Entities
 }
 
 export interface Segments {
@@ -70,7 +70,6 @@ export interface Keys {
     // also index to the Entities table.
     entityKey: Column<number>,
 
-    findEntityKey(id: string): number,
     findChainKey(entityId: string, label_asym_id: string): number,
     findResidueKey(entityId: string, label_asym_id: string, label_comp_id: string, auth_seq_id: number, pdbx_PDB_ins_code: string): number
 }

+ 19 - 13
src/mol-model/structure/model/utils/hierarchy-keys.ts

@@ -7,6 +7,7 @@
 import { Column } from 'mol-data/db'
 import { Data, Segments, Keys } from '../properties/hierarchy'
 import { Interval, Segmentation } from 'mol-data/int'
+import { Entities } from '../properties/common';
 
 function getResidueId(comp_id: string, seq_id: number, ins_code: string) {
     return `${comp_id} ${seq_id} ${ins_code}`;
@@ -26,24 +27,26 @@ function getElementSubstructureKeyMap(map: Map<number, Map<string, number>>, key
     return ret;
 }
 
-function createLookUp(entity: Map<string, number>, chain: Map<number, Map<string, number>>, residue: Map<number, Map<string, number>>) {
-    const findEntityKey: Keys['findEntityKey'] = (id) => entity.has(id) ? entity.get(id)! : -1;
+function createLookUp(entities: Entities, chain: Map<number, Map<string, number>>, residue: Map<number, Map<string, number>>) {
+    const getEntKey = entities.getEntityIndex;
     const findChainKey: Keys['findChainKey'] = (e, c) => {
-        if (!entity.has(e)) return -1;
-        const cm = chain.get(entity.get(e)!)!;
+        let eKey = getEntKey(e);
+        if (eKey < 0) return -1;
+        const cm = chain.get(eKey)!;
         if (!cm.has(c)) return -1;
         return cm.get(c)!;
     }
     const findResidueKey: Keys['findResidueKey'] = (e, c, name, seq, ins) => {
-        if (!entity.has(e)) return -1;
-        const cm = chain.get(entity.get(e)!)!;
+        let eKey = getEntKey(e);
+        if (eKey < 0) return -1;
+        const cm = chain.get(eKey)!;
         if (!cm.has(c)) return -1;
         const rm = residue.get(cm.get(c)!)!
         const id = getResidueId(name, seq, ins);
         if (!rm.has(id)) return -1;
         return rm.get(id)!;
     }
-    return { findEntityKey, findChainKey, findResidueKey };
+    return { findChainKey, findResidueKey };
 }
 
 function checkMonotonous(xs: ArrayLike<number>) {
@@ -55,10 +58,13 @@ function checkMonotonous(xs: ArrayLike<number>) {
     return true;
 }
 
-function create(data: Data, segments: Segments): Keys {
-    const { chains, residues, entities } = data;
+function missingEntity(k: string) {
+    throw new Error(`Missing entity entry for entity id '${k}'.`);
+}
+
+function create(data: Data, entities: Entities, segments: Segments): Keys {
+    const { chains, residues } = data;
 
-    const entityMap = Column.createFirstIndexMap(entities.id);
     const chainMaps = new Map<number, Map<string, number>>(), chainCounter = { index: 0 };
     const residueMaps = new Map<number, Map<string, number>>(), residueCounter = { index: 0 };
 
@@ -78,7 +84,8 @@ function create(data: Data, segments: Segments): Keys {
         const chainSegment = chainsIt.move();
         const cI = chainSegment.index;
 
-        const eKey = entityMap.get(label_entity_id.value(cI)) || 0;
+        let eKey = entities.getEntityIndex(label_entity_id.value(cI));
+        if (eKey < 0) missingEntity(label_entity_id.value(cI));
         const chainMap = getElementSubstructureKeyMap(chainMaps, eKey);
         const cKey = getElementKey(chainMap, label_asym_id.value(cI), chainCounter);
 
@@ -99,14 +106,13 @@ function create(data: Data, segments: Segments): Keys {
         }
     }
 
-    const { findEntityKey, findChainKey, findResidueKey } = createLookUp(entityMap, chainMaps, residueMaps);
+    const { findChainKey, findResidueKey } = createLookUp(entities, chainMaps, residueMaps);
 
     return {
         isMonotonous: isMonotonous && checkMonotonous(entityKey) && checkMonotonous(chainKey) && checkMonotonous(residueKey),
         residueKey: Column.ofIntArray(residueKey),
         chainKey: Column.ofIntArray(chainKey),
         entityKey: Column.ofIntArray(entityKey),
-        findEntityKey,
         findChainKey,
         findResidueKey
     };

+ 10 - 10
src/mol-model/structure/query/properties.ts

@@ -59,16 +59,16 @@ function eK(l: Element.Location) { return !Unit.isAtomic(l.unit) ? notAtomic() :
 const entity = {
     key: eK,
 
-    id: Element.property(l => l.unit.hierarchy.entities.id.value(eK(l))),
-    type: Element.property(l => l.unit.hierarchy.entities.type.value(eK(l))),
-    src_method: Element.property(l => l.unit.hierarchy.entities.src_method.value(eK(l))),
-    pdbx_description: Element.property(l => l.unit.hierarchy.entities.pdbx_description.value(eK(l))),
-    formula_weight: Element.property(l => l.unit.hierarchy.entities.formula_weight.value(eK(l))),
-    pdbx_number_of_molecules: Element.property(l => l.unit.hierarchy.entities.pdbx_number_of_molecules.value(eK(l))),
-    details: Element.property(l => l.unit.hierarchy.entities.details.value(eK(l))),
-    pdbx_mutation: Element.property(l => l.unit.hierarchy.entities.pdbx_mutation.value(eK(l))),
-    pdbx_fragment: Element.property(l => l.unit.hierarchy.entities.pdbx_fragment.value(eK(l))),
-    pdbx_ec: Element.property(l => l.unit.hierarchy.entities.pdbx_ec.value(eK(l)))
+    id: Element.property(l => l.unit.model.entities.data.id.value(eK(l))),
+    type: Element.property(l => l.unit.model.entities.data.type.value(eK(l))),
+    src_method: Element.property(l => l.unit.model.entities.data.src_method.value(eK(l))),
+    pdbx_description: Element.property(l => l.unit.model.entities.data.pdbx_description.value(eK(l))),
+    formula_weight: Element.property(l => l.unit.model.entities.data.formula_weight.value(eK(l))),
+    pdbx_number_of_molecules: Element.property(l => l.unit.model.entities.data.pdbx_number_of_molecules.value(eK(l))),
+    details: Element.property(l => l.unit.model.entities.data.details.value(eK(l))),
+    pdbx_mutation: Element.property(l => l.unit.model.entities.data.pdbx_mutation.value(eK(l))),
+    pdbx_fragment: Element.property(l => l.unit.model.entities.data.pdbx_fragment.value(eK(l))),
+    pdbx_ec: Element.property(l => l.unit.model.entities.data.pdbx_ec.value(eK(l)))
 }
 
 const unit = {