Ver Fonte

wip, custom props

David Sehnal há 6 anos atrás
pai
commit
a09e0d4875

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

@@ -11,7 +11,7 @@ import { Structure, Element } from '../structure'
 import { Model } from '../model'
 import P from '../query/properties'
 
-interface Context {
+export interface CifExportContext {
     structure: Structure,
     model: Model
 }
@@ -53,7 +53,7 @@ const atom_site_fields: CifField<Element.Location>[] = [
 ];
 
 function copy_mmCif_cat(name: keyof mmCIF_Schema) {
-    return ({ model }: Context) => {
+    return ({ model }: CifExportContext) => {
         if (model.sourceData.kind !== 'mmCIF') return CifCategory.Empty;
         const table = model.sourceData.data[name];
         if (!table || !table._rowCount) return CifCategory.Empty;
@@ -61,12 +61,12 @@ function copy_mmCif_cat(name: keyof mmCIF_Schema) {
     };
 }
 
-function _entity({ model, structure }: Context): CifCategory {
+function _entity({ model, structure }: CifExportContext): CifCategory {
     const keys = Structure.getEntityKeys(structure);
     return CifCategory.ofTable('entity', model.entities.data, keys);
 }
 
-function _atom_site({ structure }: Context): CifCategory {
+function _atom_site({ structure }: CifExportContext): CifCategory {
     return {
         data: structure,
         name: 'atom_site',
@@ -104,7 +104,7 @@ export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: S
     if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.';
     const model = models[0];
 
-    const ctx: Context[] = [{ structure, model }];
+    const ctx: CifExportContext[] = [{ structure, model }];
 
     for (const cat of Categories) {
         encoder.writeCategory(cat, ctx);

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

@@ -24,6 +24,7 @@ import { getSequence } from './mmcif/sequence';
 import { sortAtomSite } from './mmcif/sort';
 import { mmCIF_Database, mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif';
 import { Element } from '../../../structure'
+import { CustomProperties } from '../properties/custom';
 
 import mmCIF_Format = Format.mmCIF
 type AtomSite = mmCIF_Database['atom_site']
@@ -184,6 +185,7 @@ function createModel(format: mmCIF_Format, atom_site: AtomSite, previous?: Model
         sourceData: format,
         modelNum: format.data.atom_site.pdbx_PDB_model_num.value(0),
         entities,
+        symmetry: getSymmetry(format),
         atomicHierarchy,
         sequence: getSequence(format.data, entities, atomicHierarchy, modifiedResidueNameMap),
         atomicConformation: getConformation(atom_site),
@@ -193,7 +195,9 @@ function createModel(format: mmCIF_Format, atom_site: AtomSite, previous?: Model
             secondaryStructure: getSecondaryStructureMmCif(format.data, atomicHierarchy),
             modifiedResidueNameMap
         },
-        symmetry: getSymmetry(format)
+        customProperties: new CustomProperties(),
+        _staticPropertyData: Object.create(null),
+        _dynamicPropertyData: Object.create(null)
     };
 }
 

+ 6 - 4
src/mol-model/structure/model/formats/mmcif/bonds.ts

@@ -10,6 +10,8 @@ import { LinkType } from '../../types'
 import { findEntityIdByAsymId, findAtomIndexByLabelName } from './util'
 import { Column } from 'mol-data/db'
 
+// TODO: add dynamic property descriptor for this?
+
 export interface StructConn {
     getResidueEntries(residueAIndex: number, residueBIndex: number): ReadonlyArray<StructConn.Entry>
     getAtomEntries(atomIndex: number): ReadonlyArray<StructConn.Entry>
@@ -100,7 +102,7 @@ export namespace StructConn {
 
     export const PropName = '__StructConn__';
     export function fromModel(model: Model): StructConn | undefined {
-        if (model.properties[PropName]) return model.properties[PropName];
+        if (model._staticPropertyData[PropName]) return model._staticPropertyData[PropName];
 
         if (model.sourceData.kind !== 'mmCIF') return;
         const { struct_conn } = model.sourceData.data;
@@ -189,7 +191,7 @@ export namespace StructConn {
         }
 
         const ret = new StructConnImpl(entries);
-        model.properties[PropName] = ret;
+        model._staticPropertyData[PropName] = ret;
         return ret;
     }
 }
@@ -230,7 +232,7 @@ export namespace ComponentBond {
 
     export const PropName = '__ComponentBond__';
     export function fromModel(model: Model): ComponentBond | undefined {
-        if (model.properties[PropName]) return model.properties[PropName];
+        if (model._staticPropertyData[PropName]) return model._staticPropertyData[PropName];
 
         if (model.sourceData.kind !== 'mmCIF') return
         const { chem_comp_bond } = model.sourceData.data;
@@ -269,7 +271,7 @@ export namespace ComponentBond {
             entry.add(nameA, nameB, ord, flags);
         }
 
-        model.properties[PropName] = compBond;
+        model._staticPropertyData[PropName] = compBond;
         return compBond;
     }
 }

+ 11 - 4
src/mol-model/structure/model/model.ts

@@ -11,6 +11,7 @@ import { AtomicHierarchy, AtomicConformation } from './properties/atomic'
 import { ModelSymmetry } from './properties/symmetry'
 import { CoarseHierarchy, CoarseConformation } from './properties/coarse'
 import { Entities } from './properties/common';
+import { CustomProperties } from './properties/custom';
 import { SecondaryStructure } from './properties/seconday-structure';
 
 //import from_gro from './formats/gro'
@@ -35,15 +36,21 @@ interface Model extends Readonly<{
     atomicHierarchy: AtomicHierarchy,
     atomicConformation: AtomicConformation,
 
-    /** Various parts of the code can "cache" custom properties here */
     properties: {
+        // secondary structure provided by the input file
         readonly secondaryStructure: SecondaryStructure,
         // maps modified residue name to its parent
-        readonly modifiedResidueNameMap: Map<string, string>,
-        [customName: string]: any
+        readonly modifiedResidueNameMap: Map<string, string>
     },
 
-    // TODO: separate properties to "static" (propagated with trajectory) and "dynamic" (computed for each frame separately)
+    customProperties: CustomProperties,
+
+    /**
+     * Not to be accessed directly, each custom property descriptor
+     * defines property accessors that use this field to store the data.
+     */
+    _staticPropertyData: { [name: string]: any },
+    _dynamicPropertyData: { [name: string]: any },
 
     coarseHierarchy: CoarseHierarchy,
     coarseConformation: CoarseConformation

+ 8 - 0
src/mol-model/structure/model/properties/custom.ts

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

+ 25 - 0
src/mol-model/structure/model/properties/custom/collection.ts

@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { PropertyDescriptor } from './descriptor'
+
+export class CustomProperties {
+    private _list: PropertyDescriptor[] = [];
+    private _set = new Set<PropertyDescriptor>();
+
+    get all(): ReadonlyArray<PropertyDescriptor> {
+        return this._list;
+    }
+
+    add(desc: PropertyDescriptor) {
+        this._list.push(desc);
+        this._set.add(desc);
+    }
+
+    has(desc: PropertyDescriptor): boolean {
+        return this._set.has(desc);
+    }
+}

+ 18 - 0
src/mol-model/structure/model/properties/custom/descriptor.ts

@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { CifWriter } from 'mol-io/writer/cif'
+import { CifExportContext } from '../../../export/mmcif';
+
+interface PropertyDescriptor {
+    readonly isStatic: boolean,
+    readonly name: string,
+
+    /** Given a structure, returns a list of category providers used for export. */
+    getCifCategories: (ctx: CifExportContext) => CifWriter.Category.Provider[]
+}
+
+export { PropertyDescriptor }