From cdfd1992eda1f98c91b682d125da6dc1f1adaef0 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Tue, 9 Apr 2019 14:29:26 +0200 Subject: [PATCH] mol-model: custom Structure level properties (works similar way a Model properties) --- src/mol-model/structure/export/mmcif.ts | 53 ++++++++++++------- .../structure/structure/structure.ts | 29 +++++++++- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/mol-model/structure/export/mmcif.ts b/src/mol-model/structure/export/mmcif.ts index 24fcf9c71..b94604b10 100644 --- a/src/mol-model/structure/export/mmcif.ts +++ b/src/mol-model/structure/export/mmcif.ts @@ -100,8 +100,32 @@ export const mmCIF_Export_Filters = { } } +function encodeCustomProp(customProp: CustomPropertyDescriptor, ctx: CifExportContext, encoder: CifWriter.Encoder, params: encode_mmCIF_categories_Params) { + if (!customProp.cifExport || customProp.cifExport.categories.length === 0) return; + + const prefix = customProp.cifExport.prefix; + const cats = customProp.cifExport.categories; + + let propCtx = ctx; + if (customProp.cifExport.context) { + const propId = CustomPropertyDescriptor.getUUID(customProp); + if (ctx.cache[propId + '__ctx']) propCtx = ctx.cache[propId + '__ctx']; + else { + propCtx = customProp.cifExport.context(ctx) || ctx; + ctx.cache[propId + '__ctx'] = propCtx; + } + } + for (const cat of cats) { + if (params.skipCategoryNames && params.skipCategoryNames.has(cat.name)) continue; + if (cat.name.indexOf(prefix) !== 0) throw new Error(`Custom category '${cat.name}' name must start with prefix '${prefix}.'`); + encoder.writeCategory(cat, propCtx); + } +} + +type encode_mmCIF_categories_Params = { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext } + /** Doesn't start a data block */ -export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structures: Structure | Structure[], params?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext }) { +export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structures: Structure | Structure[], params?: encode_mmCIF_categories_Params) { const first = Array.isArray(structures) ? structures[0] : (structures as Structure); const models = first.models; if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.'; @@ -115,26 +139,15 @@ export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structures: } for (const customProp of models[0].customProperties.all) { - if (!customProp.cifExport || customProp.cifExport.categories.length === 0) continue; - - const prefix = customProp.cifExport.prefix; - const cats = customProp.cifExport.categories; - - let propCtx = ctx; - if (customProp.cifExport.context) { - const propId = CustomPropertyDescriptor.getUUID(customProp); - if (ctx.cache[propId + '__ctx']) propCtx = ctx.cache[propId + '__ctx']; - else { - propCtx = customProp.cifExport.context(ctx) || ctx; - ctx.cache[propId + '__ctx'] = propCtx; - } - } - for (const cat of cats) { - if (_params.skipCategoryNames && _params.skipCategoryNames.has(cat.name)) continue; - if (cat.name.indexOf(prefix) !== 0) throw new Error(`Custom category '${cat.name}' name must start with prefix '${prefix}.'`); - encoder.writeCategory(cat, propCtx); - } + encodeCustomProp(customProp, ctx, encoder, _params); + } + + const structureCustomProps = new Set<CustomPropertyDescriptor>(); + for (const s of ctx.structures) { + if (!s.hasCustomProperties) continue; + for (const p of s.customPropertyDescriptors.all) structureCustomProps.add(p); } + structureCustomProps.forEach(customProp => encodeCustomProp(customProp, ctx, encoder, _params)); } function to_mmCIF(name: string, structure: Structure, asBinary = false) { diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index b344d0e67..5243b670f 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/src/mol-model/structure/structure/structure.ts @@ -26,6 +26,7 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { idFactory } from 'mol-util/id-factory'; import { GridLookup3D } from 'mol-math/geometry'; import { UUID } from 'mol-util'; +import { CustomProperties } from '../common/custom-property'; class Structure { /** Maps unit.id to unit */ @@ -50,7 +51,9 @@ class Structure { transformHash: number, elementCount: number, polymerResidueCount: number, - coordinateSystem: SymmetryOperator + coordinateSystem: SymmetryOperator, + propertyData?: any, + customProps?: CustomProperties } = { hashCode: -1, transformHash: -1, @@ -68,6 +71,30 @@ class Structure { return this._props.elementCount; } + get hasCustomProperties() { + return !!this._props.customProps && this._props.customProps.all.length > 0; + } + + get customPropertyDescriptors() { + if (!this._props.customProps) this._props.customProps = new CustomProperties(); + return this._props.customProps; + } + + /** + * Property data unique to this instance of the structure. + */ + get currentPropertyData() { + if (!this._props.propertyData) this._props.propertyData = Object.create(null); + return this._props.propertyData; + } + + /** + * Property data of the parent structure if it exists, currentPropertyData otherwise. + */ + get inheritedPropertyData() { + return this.parent ? this.parent.currentPropertyData : this.currentPropertyData; + } + /** Count of all polymer residues in the structure */ get polymerResidueCount() { return this._props.polymerResidueCount; -- GitLab