From 15471a6af0a9e38ec370221c8c856c5f34f1dbe9 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Sat, 29 Sep 2018 18:16:50 +0200 Subject: [PATCH] refactoring CIF exporter --- src/apps/cif2bcif/converter.ts | 2 +- src/mol-io/writer/cif.ts | 4 +++ .../pdbe/structure-quality-report.ts | 23 +++++++++----- src/mol-model-props/rcsb/symmetry.ts | 2 +- .../structure/export/categories/atom_site.ts | 10 ++++--- .../export/categories/modified-residues.ts | 9 ++++-- .../export/categories/secondary-structure.ts | 15 +++++++--- src/mol-model/structure/export/mmcif.ts | 30 +++++++++---------- .../model/formats/mmcif/bonds/comp.ts | 4 +-- .../model/formats/mmcif/bonds/struct_conn.ts | 7 +++-- .../model/properties/custom/residue.ts | 25 +++++++--------- .../structure/structure/structure.ts | 10 +++++++ src/perf-tests/cif-encoder.ts | 2 +- src/servers/model/preprocess/converter.ts | 2 +- src/servers/model/preprocess/preprocess.ts | 2 +- src/servers/model/server/query.ts | 25 +++++++--------- src/servers/volume/server/query/encode.ts | 10 +++---- 17 files changed, 105 insertions(+), 77 deletions(-) diff --git a/src/apps/cif2bcif/converter.ts b/src/apps/cif2bcif/converter.ts index b17e126c4..386bba5b5 100644 --- a/src/apps/cif2bcif/converter.ts +++ b/src/apps/cif2bcif/converter.ts @@ -27,7 +27,7 @@ async function getCIF(ctx: RuntimeContext, path: string) { function getCategoryInstanceProvider(cat: CifCategory, fields: CifWriter.Field[]): CifWriter.Category { return { name: cat.name, - instance: () => ({ data: cat, fields, rowCount: cat.rowCount }) + instance: () => CifWriter.categoryInstance(fields, { data: cat, rowCount: cat.rowCount }) }; } diff --git a/src/mol-io/writer/cif.ts b/src/mol-io/writer/cif.ts index 84b555a28..c191d8a4b 100644 --- a/src/mol-io/writer/cif.ts +++ b/src/mol-io/writer/cif.ts @@ -40,6 +40,10 @@ export namespace CifWriter { fixedPoint3: E.by(E.fixedPoint(1000)).and(E.delta).and(E.integerPacking), }; + export function categoryInstance<Key, Data>(fields: Field<Key, Data>[], source: Category.DataSource): Category.Instance { + return { fields, source: [source] }; + } + export function createEncodingProviderFromCifFrame(frame: CifFrame): EncodingProvider { return { get(c, f) { diff --git a/src/mol-model-props/pdbe/structure-quality-report.ts b/src/mol-model-props/pdbe/structure-quality-report.ts index 4907860f4..47e874a65 100644 --- a/src/mol-model-props/pdbe/structure-quality-report.ts +++ b/src/mol-model-props/pdbe/structure-quality-report.ts @@ -28,17 +28,21 @@ const _Descriptor = ModelPropertyDescriptor({ categories: [{ name: 'pdbe_structure_quality_report', instance(ctx) { - const issues = StructureQualityReport.get(ctx.model); - if (typeof ctx.globalCache.pdbe_structure_quality_report !== 'undefined' && ctx.globalCache.pdbe_structure_quality_report !== ctx.model.modelNum) return CifWriter.Category.Empty; - ctx.globalCache.pdbe_structure_quality_report = ctx.model.modelNum; - return { fields: _structure_quality_report_fields, rowCount: 1, data: issues ? issues.updated : 'n/a' } + const structure = ctx.structures[0]; + const issues = StructureQualityReport.get(structure.model); + return { + fields: _structure_quality_report_fields, + source: [{ data: issues ? issues.updated : 'n/a', rowCount: 1 }] + }; } }, { name: 'pdbe_structure_quality_report_issues', instance(ctx) { - const issues = StructureQualityReport.get(ctx.model); - if (!issues || !issues.map) return CifWriter.Category.Empty; - return ResidueCustomProperty.createCifCategory(ctx, issues.map, _structure_quality_report_issues_fields); + return { + fields: _structure_quality_report_issues_fields, + source: ctx.structures.map( + s => ResidueCustomProperty.getCifDataSource(s, StructureQualityReport.getIssueMap(s.model), ctx.cache)) + }; } }] }, @@ -150,6 +154,11 @@ export namespace StructureQualityReport { return model._dynamicPropertyData.__StructureQualityReport__; } + export function getIssueMap(model: Model): IssueMap | undefined { + const data = get(model); + return data && data.map; + } + const _emptyArray: string[] = []; export function getIssues(e: StructureElement) { if (!Unit.isAtomic(e.unit)) return _emptyArray; diff --git a/src/mol-model-props/rcsb/symmetry.ts b/src/mol-model-props/rcsb/symmetry.ts index c1727ae3a..36bdd5a8e 100644 --- a/src/mol-model-props/rcsb/symmetry.ts +++ b/src/mol-model-props/rcsb/symmetry.ts @@ -22,7 +22,7 @@ const { str, int, float, Aliased, Vector, List } = Column.Schema; function getInstance(name: keyof AssemblySymmetry.Schema): (ctx: CifExportContext) => CifWriter.Category.Instance<any, any> { return function(ctx: CifExportContext) { - const assemblySymmetry = AssemblySymmetry.get(ctx.model); + const assemblySymmetry = AssemblySymmetry.get(ctx.structures[0].model); return assemblySymmetry ? Category.ofTable(assemblySymmetry.db[name]) : CifWriter.Category.Empty; } } diff --git a/src/mol-model/structure/export/categories/atom_site.ts b/src/mol-model/structure/export/categories/atom_site.ts index e80212e10..b908c7a00 100644 --- a/src/mol-model/structure/export/categories/atom_site.ts +++ b/src/mol-model/structure/export/categories/atom_site.ts @@ -51,12 +51,14 @@ const atom_site_fields = CifWriter.fields<StructureElement, Structure>() export const _atom_site: CifCategory<CifExportContext> = { name: 'atom_site', - instance({ structure }: CifExportContext) { + instance({ structures }: CifExportContext) { return { fields: atom_site_fields, - data: structure, - rowCount: structure.elementCount, - keys: () => structure.elementLocations() + source: structures.map(s => ({ + data: s, + rowCount: s.elementCount, + keys: () => s.elementLocations() + })) }; } } diff --git a/src/mol-model/structure/export/categories/modified-residues.ts b/src/mol-model/structure/export/categories/modified-residues.ts index 52886186c..0ca4666ce 100644 --- a/src/mol-model/structure/export/categories/modified-residues.ts +++ b/src/mol-model/structure/export/categories/modified-residues.ts @@ -27,7 +27,9 @@ const pdbx_struct_mod_residue_fields: CifField<number, StructureElement[]>[] = [ CifField.str('details', (i, xs) => xs[i].unit.model.properties.modifiedResidues.details.get(P.residue.label_comp_id(xs[i]))!) ]; -function getModifiedResidues({ model, structure }: CifExportContext): StructureElement[] { +function getModifiedResidues({ structures }: CifExportContext): StructureElement[] { + // TODO: can different models have differnt modified residues? + const structure = structures[0], model = structure.model; const map = model.properties.modifiedResidues.parentId; if (!map.size) return []; @@ -54,6 +56,9 @@ export const _pdbx_struct_mod_residue: CifCategory<CifExportContext> = { name: 'pdbx_struct_mod_residue', instance(ctx) { const residues = getModifiedResidues(ctx); - return { fields: pdbx_struct_mod_residue_fields, data: residues, rowCount: residues.length }; + return { + fields: pdbx_struct_mod_residue_fields, + source: [{ data: residues, rowCount: residues.length }] + }; } } \ No newline at end of file diff --git a/src/mol-model/structure/export/categories/secondary-structure.ts b/src/mol-model/structure/export/categories/secondary-structure.ts index afd936db2..2f0b3950a 100644 --- a/src/mol-model/structure/export/categories/secondary-structure.ts +++ b/src/mol-model/structure/export/categories/secondary-structure.ts @@ -18,7 +18,10 @@ export const _struct_conf: CifCategory<CifExportContext> = { name: 'struct_conf', instance(ctx) { const elements = findElements(ctx, 'helix'); - return { fields: struct_conf_fields, data: elements, rowCount: elements.length }; + return { + fields: struct_conf_fields, + source: [{ data: elements, rowCount: elements.length }] + }; } }; @@ -26,7 +29,10 @@ export const _struct_sheet_range: CifCategory<CifExportContext> = { name: 'struct_sheet_range', instance(ctx) { const elements = (findElements(ctx, 'sheet') as SSElement<SecondaryStructure.Sheet>[]).sort(compare_ssr); - return { fields: struct_sheet_range_fields, data: elements, rowCount: elements.length }; + return { + fields: struct_sheet_range_fields, + source: [{ data: elements, rowCount: elements.length }] + }; } }; @@ -63,11 +69,12 @@ interface SSElement<T extends SecondaryStructure.Element> { } function findElements<T extends SecondaryStructure.Element>(ctx: CifExportContext, kind: SecondaryStructure.Element['kind']) { - const { key, elements } = ctx.model.properties.secondaryStructure; + // TODO: encode secondary structure for different models? + const { key, elements } = ctx.structures[0].model.properties.secondaryStructure; const ssElements: SSElement<any>[] = []; - for (const unit of ctx.structure.units) { + for (const unit of ctx.structures[0].units) { // currently can only support this for "identity" operators. if (!Unit.isAtomic(unit) || !unit.conformation.operator.isIdentity) continue; diff --git a/src/mol-model/structure/export/mmcif.ts b/src/mol-model/structure/export/mmcif.ts index bd774b605..a5924f652 100644 --- a/src/mol-model/structure/export/mmcif.ts +++ b/src/mol-model/structure/export/mmcif.ts @@ -8,32 +8,30 @@ import { CifWriter } from 'mol-io/writer/cif' import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif' import { Structure } from '../structure' -import { Model } from '../model' import { _atom_site } from './categories/atom_site'; import CifCategory = CifWriter.Category import { _struct_conf, _struct_sheet_range } from './categories/secondary-structure'; import { _pdbx_struct_mod_residue } from './categories/modified-residues'; export interface CifExportContext { - structure: Structure, - model: Model, - localCache: any, - /** useful when exporting multiple models at the same time */ - globalCache: any + structures: Structure[], + cache: any } export namespace CifExportContext { - export function create(structures: Structure | Structure[]): CifExportContext[] { - const globalCache = Object.create(null); - if (Array.isArray(structures)) return structures.map(structure => ({ structure, model: structure.models[0], localCache: Object.create(null), globalCache })); - return [{ structure: structures, model: structures.models[0], localCache: Object.create(null), globalCache }]; + export function create(structures: Structure | Structure[]): CifExportContext { + return { + structures: Array.isArray(structures) ? structures : [structures], + cache: Object.create(null) + }; } } function copy_mmCif_category(name: keyof mmCIF_Schema): CifCategory<CifExportContext> { return { name, - instance({ model }) { + instance({ structures }) { + const model = structures[0].model; if (model.sourceData.kind !== 'mmCIF') return CifCategory.Empty; const table = model.sourceData.data[name]; if (!table || !table._rowCount) return CifCategory.Empty; @@ -44,9 +42,9 @@ function copy_mmCif_category(name: keyof mmCIF_Schema): CifCategory<CifExportCon const _entity: CifCategory<CifExportContext> = { name: 'entity', - instance({ structure, model}) { - const keys = Structure.getEntityKeys(structure); - return CifCategory.ofTable(model.entities.data, keys); + instance({ structures}) { + const keys = Structure.getEntityKeys(structures[0]); + return CifCategory.ofTable(structures[0].model.entities.data, keys); } } @@ -103,13 +101,13 @@ export const mmCIF_Export_Filters = { } /** 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?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext }) { 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.'; const _params = params || { }; - const ctx: CifExportContext[] = params && params.exportCtx ? params.exportCtx : CifExportContext.create(structures); + const ctx: CifExportContext = params && params.exportCtx ? params.exportCtx : CifExportContext.create(structures); for (const cat of Categories) { if (_params.skipCategoryNames && _params.skipCategoryNames.has(cat.name)) continue; diff --git a/src/mol-model/structure/model/formats/mmcif/bonds/comp.ts b/src/mol-model/structure/model/formats/mmcif/bonds/comp.ts index 7aab5ed22..430480733 100644 --- a/src/mol-model/structure/model/formats/mmcif/bonds/comp.ts +++ b/src/mol-model/structure/model/formats/mmcif/bonds/comp.ts @@ -26,10 +26,10 @@ export namespace ComponentBond { categories: [{ name: 'chem_comp_bond', instance(ctx) { - const chem_comp_bond = getChemCompBond(ctx.model); + const chem_comp_bond = getChemCompBond(ctx.structures[0].model); if (!chem_comp_bond) return CifWriter.Category.Empty; - const comp_names = getUniqueResidueNames(ctx.structure); + const comp_names = getUniqueResidueNames(ctx.structures[0]); const { comp_id, _rowCount } = chem_comp_bond; const indices: number[] = []; for (let i = 0; i < _rowCount; i++) { diff --git a/src/mol-model/structure/model/formats/mmcif/bonds/struct_conn.ts b/src/mol-model/structure/model/formats/mmcif/bonds/struct_conn.ts index 3296debca..486c071a1 100644 --- a/src/mol-model/structure/model/formats/mmcif/bonds/struct_conn.ts +++ b/src/mol-model/structure/model/formats/mmcif/bonds/struct_conn.ts @@ -31,10 +31,11 @@ export namespace StructConn { categories: [{ name: 'struct_conn', instance(ctx) { - const struct_conn = getStructConn(ctx.model); + const structure = ctx.structures[0], model = structure.model; + const struct_conn = getStructConn(model); if (!struct_conn) return CifWriter.Category.Empty; - const strConn = get(ctx.model); + const strConn = get(model); if (!strConn || strConn.entries.length === 0) return CifWriter.Category.Empty; const foundAtoms = new Set<ElementIndex>(); @@ -45,7 +46,7 @@ export namespace StructConn { for (let i = 0, _i = partners.length; i < _i; i++) { const atom = partners[i].atomIndex; if (foundAtoms.has(atom)) continue; - if (hasAtom(ctx.structure, atom)) { + if (hasAtom(structure, atom)) { foundAtoms.add(atom); } else { hasAll = false; diff --git a/src/mol-model/structure/model/properties/custom/residue.ts b/src/mol-model/structure/model/properties/custom/residue.ts index 0b9b480b7..ba79b8d7b 100644 --- a/src/mol-model/structure/model/properties/custom/residue.ts +++ b/src/mol-model/structure/model/properties/custom/residue.ts @@ -7,7 +7,6 @@ import { ResidueIndex } from '../../indexing'; import { Unit, Structure, StructureElement } from '../../../structure'; import { Segmentation } from 'mol-data/int'; -import { CifExportContext } from '../../../export/mmcif'; import { UUID } from 'mol-util'; import { CifWriter } from 'mol-io/writer/cif'; @@ -20,25 +19,23 @@ export interface ResidueCustomProperty<T = any> { export namespace ResidueCustomProperty { export interface ExportCtx<T> { - exportCtx: CifExportContext, elements: StructureElement[], property(index: number): T }; - function getExportCtx<T>(exportCtx: CifExportContext, prop: ResidueCustomProperty<T>): ExportCtx<T> { - if (exportCtx.localCache[prop.id]) return exportCtx.localCache[prop.id]; - const residueIndex = exportCtx.model.atomicHierarchy.residueAtomSegments.index; - const elements = getStructureElements(exportCtx.structure, prop); - return { - exportCtx, - elements, - property: i => prop.get(residueIndex[elements[i].element])! - } + function getExportCtx<T>(prop: ResidueCustomProperty<T>, structure: Structure): ExportCtx<T> { + const residueIndex = structure.model.atomicHierarchy.residueAtomSegments.index; + const elements = getStructureElements(structure, prop); + return { elements, property: i => prop.get(residueIndex[elements[i].element])! }; } - export function createCifCategory<T>(ctx: CifExportContext, prop: ResidueCustomProperty<T>, fields: CifWriter.Field<number, ExportCtx<T>>[]): CifWriter.Category.Instance { - const data = getExportCtx(ctx, prop); - return { fields, data, rowCount: data.elements.length }; + export function getCifDataSource<T>(structure: Structure, prop: ResidueCustomProperty<T> | undefined, cache: any): CifWriter.Category.Instance['source'][0] { + if (!prop) return { rowCount: 0 }; + if (cache && cache[prop.id]) return cache[prop.id]; + const data = getExportCtx(prop, structure); + const ret = { data, rowCount: data.elements.length }; + if (cache) cache[prop.id] = ret; + return ret; } class FromMap<T> implements ResidueCustomProperty<T> { diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index b93f7e96c..7f41cc5fc 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/src/mol-model/structure/structure/structure.ts @@ -38,6 +38,7 @@ class Structure { unitSymmetryGroups?: ReadonlyArray<Unit.SymmetryGroup>, carbohydrates?: Carbohydrates, models?: ReadonlyArray<Model>, + model?: Model, hashCode: number, elementCount: number, polymerResidueCount: number, @@ -128,6 +129,15 @@ class Structure { return this._props.models; } + /** If the structure is based on a single model, return it. Otherwise throw an exception. */ + get model(): Model { + if (this._props.model) return this._props.model; + const models = this.models; + if (models.length > 1) throw new Error('The structre is based on multiple models.'); + this._props.model = models[0]; + return this._props.model; + } + hasElement(e: StructureElement) { if (!this.unitMap.has(e.unit.id)) return false; return SortedArray.has(this.unitMap.get(e.unit.id).elements, e.element); diff --git a/src/perf-tests/cif-encoder.ts b/src/perf-tests/cif-encoder.ts index f8f2ab18c..59f0eb3f6 100644 --- a/src/perf-tests/cif-encoder.ts +++ b/src/perf-tests/cif-encoder.ts @@ -23,7 +23,7 @@ function getCat(name: string): CifWriter.Category { return { name, instance(ctx: { fields: CifWriter.Field[], rowCount: number }) { - return { data: void 0, fields: ctx.fields, rowCount: ctx.rowCount }; + return { fields: ctx.fields, source: [{ rowCount: ctx.rowCount }] }; } }; } diff --git a/src/servers/model/preprocess/converter.ts b/src/servers/model/preprocess/converter.ts index 66d77fcb4..0ef1bb1b5 100644 --- a/src/servers/model/preprocess/converter.ts +++ b/src/servers/model/preprocess/converter.ts @@ -12,7 +12,7 @@ import { Task } from 'mol-task'; function getCategoryInstanceProvider(cat: CifCategory, fields: CifWriter.Field[]): CifWriter.Category { return { name: cat.name, - instance: () => ({ data: cat, fields, rowCount: cat.rowCount }) + instance: () => CifWriter.categoryInstance(fields, { data: cat, rowCount: cat.rowCount }) }; } diff --git a/src/servers/model/preprocess/preprocess.ts b/src/servers/model/preprocess/preprocess.ts index 371ae472a..187a017b7 100644 --- a/src/servers/model/preprocess/preprocess.ts +++ b/src/servers/model/preprocess/preprocess.ts @@ -36,7 +36,7 @@ export async function preprocessFile(filename: string, propertyProvider?: ModelP } } -function encode(structure: Structure, header: string, categories: CifWriter.Category[], encoder: CifWriter.Encoder, exportCtx: CifExportContext[], writer: Writer) { +function encode(structure: Structure, header: string, categories: CifWriter.Category[], encoder: CifWriter.Encoder, exportCtx: CifExportContext, writer: Writer) { const skipCategoryNames = new Set<string>(categories.map(c => c.name)); encoder.startDataBlock(header); for (const cat of categories) { diff --git a/src/servers/model/server/query.ts b/src/servers/model/server/query.ts index 09603e183..0c80ae56c 100644 --- a/src/servers/model/server/query.ts +++ b/src/servers/model/server/query.ts @@ -70,8 +70,8 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> { perf.start('encode'); encoder.startDataBlock(sourceStructures[0].models[0].label.toUpperCase()); - encoder.writeCategory(_model_server_result, [job]); - encoder.writeCategory(_model_server_params, [job]); + encoder.writeCategory(_model_server_result, job); + encoder.writeCategory(_model_server_params, job); // encoder.setFilter(mmCIF_Export_Filters.onlyPositions); encode_mmCIF_categories(encoder, result); @@ -84,7 +84,7 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> { encodeTimeMs: perf.time('encode') }; - encoder.writeCategory(_model_server_stats, [stats]); + encoder.writeCategory(_model_server_stats, stats); encoder.encode(); ConsoleLogger.logId(job.id, 'Query', 'Encoded.'); return encoder; @@ -101,9 +101,9 @@ function getEncodingProvider(structure: StructureWrapper) { function doError(job: Job, e: any) { const encoder = CifWriter.createEncoder({ binary: job.responseFormat.isBinary, encoderName: `ModelServer ${Version}` }); - encoder.writeCategory(_model_server_result, [job]); - encoder.writeCategory(_model_server_params, [job]); - encoder.writeCategory(_model_server_error, ['' + e]); + encoder.writeCategory(_model_server_result, job); + encoder.writeCategory(_model_server_params, job); + encoder.writeCategory(_model_server_error, '' + e); encoder.encode(); return encoder; } @@ -155,12 +155,12 @@ const _model_server_stats_fields: CifField<number, Stats>[] = [ const _model_server_result: CifWriter.Category<Job> = { name: 'model_server_result', - instance: (job) => ({ data: job, fields: _model_server_result_fields, rowCount: 1 }) + instance: (job) => CifWriter.categoryInstance(_model_server_result_fields,{ data: job, rowCount: 1 }) }; const _model_server_error: CifWriter.Category<string> = { name: 'model_server_error', - instance: (message) => ({ data: message, fields: _model_server_error_fields, rowCount: 1 }) + instance: (message) => CifWriter.categoryInstance(_model_server_error_fields, { data: message, rowCount: 1 }) }; const _model_server_params: CifWriter.Category<Job> = { @@ -170,17 +170,12 @@ const _model_server_params: CifWriter.Category<Job> = { for (const k of Object.keys(job.normalizedParams)) { params.push([k, JSON.stringify(job.normalizedParams[k])]); } - return { - data: params, - - fields: _model_server_params_fields, - rowCount: params.length - } + return CifWriter.categoryInstance(_model_server_params_fields, { data: params, rowCount: params.length }); } }; const _model_server_stats: CifWriter.Category<Stats> = { name: 'model_server_stats', - instance: (stats) => ({ data: stats, fields: _model_server_stats_fields, rowCount: 1 }) + instance: (stats) => CifWriter.categoryInstance(_model_server_stats_fields, { data: stats, rowCount: 1 }) } \ No newline at end of file diff --git a/src/servers/volume/server/query/encode.ts b/src/servers/volume/server/query/encode.ts index a754ef489..f456c9edf 100644 --- a/src/servers/volume/server/query/encode.ts +++ b/src/servers/volume/server/query/encode.ts @@ -102,7 +102,7 @@ const _volume_data_3d_info: CifWriter.Category<ResultContext> = { sampledValuesInfo: result.query.data.header.sampling[result.query.samplingInfo.sampling.index].valuesInfo[result.channelIndex] }; - return { data: ctx, fields: _volume_data_3d_info_fields, rowCount: 1 } + return { fields: _volume_data_3d_info_fields, source: [{ data: ctx, rowCount: 1 }] } } }; @@ -136,7 +136,7 @@ const _volume_data_3d: CifWriter.Category<ResultContext> = { } const fields = [CifWriter.Field.float('values', _volume_data_3d_number, { encoder, typedArray, digitCount: 6 })]; - return { data, fields, rowCount: data.length }; + return CifWriter.categoryInstance(fields, { data, rowCount: data.length }); } } @@ -174,12 +174,12 @@ const _density_server_result_fields = [ const _density_server_result: CifWriter.Category<Data.QueryContext> = { name: 'density_server_result', - instance: ctx => ({ data: ctx, fields: _density_server_result_fields, rowCount: 1 }) + instance: ctx => CifWriter.categoryInstance(_density_server_result_fields, { data: ctx, rowCount: 1 }) } function write(encoder: CifWriter.Encoder, query: Data.QueryContext) { encoder.startDataBlock('SERVER'); - encoder.writeCategory(_density_server_result, [query]); + encoder.writeCategory(_density_server_result, query); switch (query.kind) { case 'Data': @@ -189,7 +189,7 @@ function write(encoder: CifWriter.Encoder, query: Data.QueryContext) { const header = query.data.header; for (let i = 0; i < header.channels.length; i++) { encoder.startDataBlock(header.channels[i]); - const ctx: ResultContext[] = [{ query, channelIndex: i }]; + const ctx: ResultContext = { query, channelIndex: i }; encoder.writeCategory(_volume_data_3d_info, ctx); encoder.writeCategory(_volume_data_3d, ctx); -- GitLab