Browse Source

More CIF writer refactoring

David Sehnal 6 years ago
parent
commit
663487b8b1

+ 3 - 3
src/apps/cif2bcif/converter.ts

@@ -5,7 +5,7 @@
  */
 
 import CIF, { CifCategory } from 'mol-io/reader/cif'
-import { CIFCategory, createCIFEncoder } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 import * as fs from 'fs'
 import classify from './field-classifier'
 
@@ -18,7 +18,7 @@ async function getCIF(path: string) {
     return parsed.result;
 }
 
-function getCategoryInstanceProvider(cat: CifCategory): CIFCategory.Provider {
+function getCategoryInstanceProvider(cat: CifCategory): CifWriter.Category.Provider {
     return function (ctx: any) {
         return {
             data: cat,
@@ -32,7 +32,7 @@ function getCategoryInstanceProvider(cat: CifCategory): CIFCategory.Provider {
 export default async function convert(path: string, asText = false) {
     const cif = await getCIF(path);
 
-    const encoder = createCIFEncoder({ binary: !asText, encoderName: 'mol* cif2bcif' });
+    const encoder = CifWriter.createEncoder({ binary: !asText, encoderName: 'mol* cif2bcif' });
     for (const b of cif.blocks) {
         encoder.startDataBlock(b.header);
         for (const c of b.categoryNames) {

+ 5 - 5
src/apps/cif2bcif/field-classifier.ts

@@ -6,14 +6,14 @@
 
 import { Column } from 'mol-data/db'
 import { CifField } from 'mol-io/reader/cif/data-model'
-import { CIFField } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 
 const intRegex = /^-?\d+$/
 const floatRegex = /^-?(([0-9]+)[.]?|([0-9]*[.][0-9]+))([(][0-9]+[)])?([eE][+-]?[0-9]+)?/
 
 // Classify a cif field as str, int or float based the data it contains.
 // To classify a field as int or float all items are checked.
-function classify(name: string, field: CifField): CIFField {
+function classify(name: string, field: CifField): CifWriter.Field {
     let floatCount = 0, hasString = false;
     for (let i = 0, _i = field.rowCount; i < _i; i++) {
         const k = field.valueKind(i);
@@ -24,9 +24,9 @@ function classify(name: string, field: CifField): CIFField {
         else { hasString = true; break; }
     }
 
-    if (hasString) return { name, type: CIFField.Type.Str, value: field.str, valueKind: field.valueKind };
-    if (floatCount > 0) return { name, type: CIFField.Type.Float, value: field.float, valueKind: field.valueKind };
-    return { name, type: CIFField.Type.Int, value: field.int, valueKind: field.valueKind };
+    if (hasString) return { name, type: CifWriter.Field.Type.Str, value: field.str, valueKind: field.valueKind };
+    if (floatCount > 0) return { name, type: CifWriter.Field.Type.Float, value: field.float, valueKind: field.valueKind };
+    return { name, type: CifWriter.Field.Type.Int, value: field.int, valueKind: field.valueKind };
 }
 
 export default classify;

+ 3 - 3
src/apps/combine-mmcif/index.ts

@@ -17,7 +17,7 @@ import { Progress } from 'mol-task'
 import { Database, Table, DatabaseCollection } from 'mol-data/db'
 import CIF from 'mol-io/reader/cif'
 // import { CCD_Schema } from 'mol-io/reader/cif/schema/ccd'
-import { CIFEncoder, createCIFEncoder } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 import { mmCIF_Schema, mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif';
 import { CCD_Schema } from 'mol-io/reader/cif/schema/ccd';
 import { BIRD_Schema } from 'mol-io/reader/cif/schema/bird';
@@ -85,8 +85,8 @@ async function parseCif(data: string|Uint8Array) {
 }
 
 export function getEncodedCif(name: string, database: Database<Database.Schema>, binary = false) {
-    const encoder = createCIFEncoder({ binary, encoderName: 'mol*' });
-    CIFEncoder.writeDatabase(encoder, name, database)
+    const encoder = CifWriter.createEncoder({ binary, encoderName: 'mol*' });
+    CifWriter.Encoder.writeDatabase(encoder, name, database)
     return encoder.getData();
 }
 

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

@@ -5,13 +5,13 @@
  */
 
 import { Table } from 'mol-data/db'
-import { CIFEncoder, createCIFEncoder as createEncoder } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 import * as S from './schemas'
 import { getCategoryInstanceProvider } from './utils'
 
 export default function create(allData: any) {
     const mols = Object.keys(allData);
-    const enc = createEncoder();
+    const enc = CifWriter.createEncoder();
     enc.startDataBlock(mols[0]);
 
     if (!mols.length) return enc.getData();
@@ -36,7 +36,7 @@ interface DomainAnnotation {
 }
 type MappingRow = Table.Row<S.mapping>;
 
-function writeDomain(enc: CIFEncoder, domain: DomainAnnotation | undefined) {
+function writeDomain(enc: CifWriter.Encoder, domain: DomainAnnotation | undefined) {
     if (!domain) return;
     enc.writeCategory(getCategoryInstanceProvider(`pdbx_${domain.name}_domain_annotation`, domain.domains));
     enc.writeCategory(getCategoryInstanceProvider(`pdbx_${domain.name}_domain_mapping`, domain.mappings));

+ 4 - 4
src/apps/domain-annotation-server/utils.ts

@@ -5,7 +5,7 @@
  */
 
 import { Table } from 'mol-data/db'
-import { CIFField, CIFCategory } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 
 function columnValue(k: string) {
     return (i: number, d: any) => d[k].value(i);
@@ -16,16 +16,16 @@ function columnValueKind(k: string) {
 }
 
 function ofSchema(schema: Table.Schema) {
-    const fields: CIFField[] = [];
+    const fields: CifWriter.Field[] = [];
     for (const k of Object.keys(schema)) {
         const t = schema[k];
-        const type: any = t.valueType === 'str' ? CIFField.Type.Str : t.valueType === 'int' ? CIFField.Type.Int : CIFField.Type.Float;
+        const type: any = t.valueType === 'str' ? CifWriter.Field.Type.Str : t.valueType === 'int' ? CifWriter.Field.Type.Int : CifWriter.Field.Type.Float;
         fields.push({ name: k, type, value: columnValue(k), valueKind: columnValueKind(k) })
     }
     return fields;
 }
 
-export function getCategoryInstanceProvider(name: string, table: Table<any>): CIFCategory.Provider {
+export function getCategoryInstanceProvider(name: string, table: Table<any>): CifWriter.Category.Provider {
     return () => {
         return {
             data: table,

+ 16 - 5
src/mol-io/writer/cif.ts

@@ -7,11 +7,22 @@
 
 import TextCIFEncoder from './cif/encoder/text'
 import BinaryCIFEncoder from './cif/encoder/binary'
-import { CIFEncoder } from './cif/encoder'
+import * as _Encoder from './cif/encoder'
 
-export * from './cif/encoder'
+// export * from './cif/encoder'
 
-export function createCIFEncoder(params?: { binary?: boolean, encoderName?: string }): CIFEncoder {
-    const { binary = false, encoderName = 'mol*' } = params || {};
-    return binary ? new BinaryCIFEncoder(encoderName) : new TextCIFEncoder();
+// export function createCIFEncoder(params?: { binary?: boolean, encoderName?: string }): CIFEncoder {
+//     const { binary = false, encoderName = 'mol*' } = params || {};
+//     return binary ? new BinaryCIFEncoder(encoderName) : new TextCIFEncoder();
+//}
+
+export namespace CifWriter {
+    export import Encoder = _Encoder.CIFEncoder
+    export import Category = _Encoder.CIFCategory
+    export import Field = _Encoder.CIFField
+
+    export function createEncoder(params?: { binary?: boolean, encoderName?: string }): Encoder {
+        const { binary = false, encoderName = 'mol*' } = params || {};
+        return binary ? new BinaryCIFEncoder(encoderName) : new TextCIFEncoder();
+    }
 }

+ 34 - 31
src/mol-model/structure/export/mmcif.ts

@@ -5,7 +5,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { CIFEncoder, createCIFEncoder, CIFCategory, CIFField } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 // import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif'
 import { Structure, Element } from '../structure'
 import { Model } from '../model'
@@ -16,40 +16,43 @@ interface Context {
     model: Model
 }
 
-const atom_site_fields: CIFField<Element.Location>[] = [
-    CIFField.str('group_PDB', P.residue.group_PDB),
-    CIFField.int('id', P.atom.id),
-    CIFField.str('type_symbol', P.atom.type_symbol as any),
-    CIFField.str('label_atom_id', P.atom.label_atom_id),
-    CIFField.str('label_alt_id', P.atom.label_alt_id),
+import CifField = CifWriter.Field
+import CifCategory = CifWriter.Category
 
-    CIFField.str('label_comp_id', P.residue.label_comp_id),
-    CIFField.int('label_seq_id', P.residue.label_seq_id),
-    CIFField.str('pdbx_PDB_ins_code', P.residue.pdbx_PDB_ins_code),
+const atom_site_fields: CifField<Element.Location>[] = [
+    CifField.str('group_PDB', P.residue.group_PDB),
+    CifField.int('id', P.atom.id),
+    CifField.str('type_symbol', P.atom.type_symbol as any),
+    CifField.str('label_atom_id', P.atom.label_atom_id),
+    CifField.str('label_alt_id', P.atom.label_alt_id),
 
-    CIFField.str('label_asym_id', P.chain.label_asym_id),
-    CIFField.str('label_entity_id', P.chain.label_entity_id),
+    CifField.str('label_comp_id', P.residue.label_comp_id),
+    CifField.int('label_seq_id', P.residue.label_seq_id),
+    CifField.str('pdbx_PDB_ins_code', P.residue.pdbx_PDB_ins_code),
 
-    CIFField.float('Cartn_x', P.atom.x),
-    CIFField.float('Cartn_y', P.atom.y),
-    CIFField.float('Cartn_z', P.atom.z),
-    CIFField.float('occupancy', P.atom.occupancy),
-    CIFField.int('pdbx_formal_charge', P.atom.pdbx_formal_charge),
+    CifField.str('label_asym_id', P.chain.label_asym_id),
+    CifField.str('label_entity_id', P.chain.label_entity_id),
 
-    CIFField.str('auth_atom_id', P.atom.auth_atom_id),
-    CIFField.str('auth_comp_id', P.residue.auth_comp_id),
-    CIFField.int('auth_seq_id', P.residue.auth_seq_id),
-    CIFField.str('auth_asym_id', P.chain.auth_asym_id),
+    CifField.float('Cartn_x', P.atom.x),
+    CifField.float('Cartn_y', P.atom.y),
+    CifField.float('Cartn_z', P.atom.z),
+    CifField.float('occupancy', P.atom.occupancy),
+    CifField.int('pdbx_formal_charge', P.atom.pdbx_formal_charge),
 
-    CIFField.int('pdbx_PDB_model_num', P.unit.model_num),
-    CIFField.str('operator_name', P.unit.operator_name)
+    CifField.str('auth_atom_id', P.atom.auth_atom_id),
+    CifField.str('auth_comp_id', P.residue.auth_comp_id),
+    CifField.int('auth_seq_id', P.residue.auth_seq_id),
+    CifField.str('auth_asym_id', P.chain.auth_asym_id),
+
+    CifField.int('pdbx_PDB_model_num', P.unit.model_num),
+    CifField.str('operator_name', P.unit.operator_name)
 ];
 
-function entityProvider({ model }: Context): CIFCategory {
-    return CIFCategory.ofTable('entity', model.entities.data);
+function entityProvider({ model }: Context): CifCategory {
+    return CifCategory.ofTable('entity', model.entities.data);
 }
 
-function atomSiteProvider({ structure }: Context): CIFCategory {
+function atomSiteProvider({ structure }: Context): CifCategory {
     return {
         data: void 0,
         name: 'atom_site',
@@ -60,7 +63,7 @@ function atomSiteProvider({ structure }: Context): CIFCategory {
 }
 
 /** Doesn't start a data block */
-export function encode_mmCIF_categories(encoder: CIFEncoder, structure: Structure) {
+export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: Structure) {
     const models = Structure.getModels(structure);
     if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.';
     const model = models[0];
@@ -71,10 +74,10 @@ export function encode_mmCIF_categories(encoder: CIFEncoder, structure: Structur
 }
 
 function to_mmCIF(name: string, structure: Structure, asBinary = false) {
-    const w = createCIFEncoder({ binary: asBinary });
-    w.startDataBlock(name);
-    encode_mmCIF_categories(w, structure);
-    return w.getData();
+    const enc = CifWriter.createEncoder({ binary: asBinary });
+    enc.startDataBlock(name);
+    encode_mmCIF_categories(enc, structure);
+    return enc.getData();
 }
 
 export default to_mmCIF

+ 15 - 15
src/perf-tests/cif-encoder.ts

@@ -4,21 +4,21 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
- import { CIFCategory, CIFField, createCIFEncoder } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 
-const category1fields: CIFField[] = [
-    CIFField.str('f1', i => 'v' + i),
-    CIFField.int('f2', i => i * i),
-    CIFField.float('f3', i => Math.random()),
+const category1fields: CifWriter.Field[] = [
+    CifWriter.Field.str('f1', i => 'v' + i),
+    CifWriter.Field.int('f2', i => i * i),
+    CifWriter.Field.float('f3', i => Math.random()),
 ];
 
-const category2fields: CIFField[] = [
-    CIFField.str('e1', i => 'v\n' + i),
-    CIFField.int('e2', i => i * i),
-    CIFField.float('e3', i => Math.random()),
+const category2fields: CifWriter.Field[] = [
+    CifWriter.Field.str('e1', i => 'v\n' + i),
+    CifWriter.Field.int('e2', i => i * i),
+    CifWriter.Field.float('e3', i => Math.random()),
 ];
 
-function getInstance(ctx: { name: string, fields: CIFField[], rowCount: number }): CIFCategory {
+function getInstance(ctx: { name: string, fields: CifWriter.Field[], rowCount: number }): CifWriter.Category {
     return {
         data: void 0,
         name: ctx.name,
@@ -27,9 +27,9 @@ function getInstance(ctx: { name: string, fields: CIFField[], rowCount: number }
     }
 }
 
-const w = createCIFEncoder();
+const enc = CifWriter.createEncoder();
 
-w.startDataBlock('test');
-w.writeCategory(getInstance, [{ rowCount: 5, name: 'cat1', fields: category1fields }]);
-w.writeCategory(getInstance, [{ rowCount: 1, name: 'cat2', fields: category2fields  }]);
-console.log(w.getData());
+enc.startDataBlock('test');
+enc.writeCategory(getInstance, [{ rowCount: 5, name: 'cat1', fields: category1fields }]);
+enc.writeCategory(getInstance, [{ rowCount: 1, name: 'cat2', fields: category2fields  }]);
+console.log(enc.getData());

+ 15 - 13
src/servers/model/server/query.ts

@@ -11,7 +11,7 @@ import Config from '../config';
 import { Progress, now } from 'mol-task';
 import { ConsoleLogger } from 'mol-util/console-logger';
 import Writer from 'mol-io/writer/writer';
-import { CIFCategory, CIFField, createCIFEncoder } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 import { encode_mmCIF_categories } from 'mol-model/structure/export/mmcif';
 import { Selection } from 'mol-model/structure';
 import Version from '../version'
@@ -74,7 +74,7 @@ export async function resolveRequest(req: Request, writer: Writer) {
 
     ConsoleLogger.logId(req.id, 'Query', 'Query finished.');
 
-    const encoder = createCIFEncoder({ binary: req.responseFormat.isBinary, encoderName: `ModelServer ${Version}` });
+    const encoder = CifWriter.createEncoder({ binary: req.responseFormat.isBinary, encoderName: `ModelServer ${Version}` });
 
     perf.start('encode');
     encoder.startDataBlock('result');
@@ -105,18 +105,20 @@ export function abortingObserver(p: Progress) {
     }
 }
 
-function string<T>(name: string, str: (data: T, i: number) => string, isSpecified?: (data: T) => boolean): CIFField<number, T> {
+import CifField = CifWriter.Field
+
+function string<T>(name: string, str: (data: T, i: number) => string, isSpecified?: (data: T) => boolean): CifField<number, T> {
     if (isSpecified) {
-        return CIFField.str(name,  (i, d) => str(d, i), { valueKind: (i, d) => isSpecified(d) ? Column.ValueKind.Present : Column.ValueKind.NotPresent });
+        return CifField.str(name,  (i, d) => str(d, i), { valueKind: (i, d) => isSpecified(d) ? Column.ValueKind.Present : Column.ValueKind.NotPresent });
     }
-    return CIFField.str(name,  (i, d) => str(d, i));
+    return CifField.str(name,  (i, d) => str(d, i));
 }
 
-function int32<T>(name: string, value: (data: T) => number): CIFField<number, T> {
-    return CIFField.int(name, (i, d) => value(d));
+function int32<T>(name: string, value: (data: T) => number): CifField<number, T> {
+    return CifField.int(name, (i, d) => value(d));
 }
 
-const _model_server_result_fields: CIFField<number, Request>[] = [
+const _model_server_result_fields: CifField<number, Request>[] = [
     string<Request>('request_id', ctx => '' + ctx.id),
     string<Request>('datetime_utc', ctx => ctx.datetime_utc),
     string<Request>('server_version', ctx => Version),
@@ -125,12 +127,12 @@ const _model_server_result_fields: CIFField<number, Request>[] = [
     string<Request>('entry_id', ctx => ctx.entryId),
 ];
 
-const _model_server_params_fields: CIFField<number, string[]>[] = [
+const _model_server_params_fields: CifField<number, string[]>[] = [
     string<string[]>('name', (ctx, i) => ctx[i][0]),
     string<string[]>('value', (ctx, i) => ctx[i][1])
 ];
 
-const _model_server_stats_fields: CIFField<number, Stats>[] = [
+const _model_server_stats_fields: CifField<number, Stats>[] = [
     int32<Stats>('io_time_ms', ctx => ctx.structure.info.readTime | 0),
     int32<Stats>('parse_time_ms', ctx => ctx.structure.info.parseTime | 0),
     int32<Stats>('create_model_time_ms', ctx => ctx.structure.info.createModelTime | 0),
@@ -139,7 +141,7 @@ const _model_server_stats_fields: CIFField<number, Stats>[] = [
 ];
 
 
-function _model_server_result(request: Request): CIFCategory {
+function _model_server_result(request: Request): CifWriter.Category {
     return {
         data: request,
         name: 'model_server_result',
@@ -148,7 +150,7 @@ function _model_server_result(request: Request): CIFCategory {
     };
 }
 
-function _model_server_params(request: Request): CIFCategory {
+function _model_server_params(request: Request): CifWriter.Category {
     const params: string[][] = [];
     for (const k of Object.keys(request.normalizedParams)) {
         params.push([k, '' + request.normalizedParams[k]]);
@@ -161,7 +163,7 @@ function _model_server_params(request: Request): CIFCategory {
     };
 }
 
-function _model_server_stats(stats: Stats): CIFCategory {
+function _model_server_stats(stats: Stats): CifWriter.Category {
     return {
         data: stats,
         name: 'model_server_stats',

+ 15 - 18
src/servers/volume/server/query/encode.ts

@@ -6,7 +6,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { CIFEncoder, CIFCategory, CIFField, createCIFEncoder } from 'mol-io/writer/cif'
+import { CifWriter } from 'mol-io/writer/cif'
 import * as Data from './data-model'
 import * as Coords from '../algebra/coordinate'
 import VERSION from '../version'
@@ -15,7 +15,7 @@ import { Column } from 'mol-data/db';
 import { ArrayEncoding, ArrayEncoder } from 'mol-io/common/binary-cif';
 
 export default function encode(query: Data.QueryContext, output: Data.QueryOutputStream) {
-    let w = createCIFEncoder({ binary: query.params.asBinary, encoderName: `VolumeServer ${VERSION}` });
+    let w = CifWriter.createEncoder({ binary: query.params.asBinary, encoderName: `VolumeServer ${VERSION}` });
     write(w, query);
     w.encode();
     w.writeTo(output);
@@ -26,21 +26,19 @@ interface ResultContext {
     channelIndex: number
 }
 
-type FieldDesc<T> = CIFField<number, T>
-
-function string<T>(name: string, str: (data: T) => string, isSpecified?: (data: T) => boolean): CIFField<number, T> {
+function string<T>(name: string, str: (data: T) => string, isSpecified?: (data: T) => boolean): CifWriter.Field<number, T> {
     if (isSpecified) {
-        return CIFField.str(name,  (i, d) => str(d), { valueKind: (i, d) => isSpecified(d) ? Column.ValueKind.Present : Column.ValueKind.NotPresent });
+        return CifWriter.Field.str(name,  (i, d) => str(d), { valueKind: (i, d) => isSpecified(d) ? Column.ValueKind.Present : Column.ValueKind.NotPresent });
     }
-    return CIFField.str(name,  (i, d) => str(d));
+    return CifWriter.Field.str(name,  (i, d) => str(d));
 }
 
-function int32<T>(name: string, value: (data: T) => number): CIFField<number, T> {
-    return CIFField.int(name, (i, d) => value(d));
+function int32<T>(name: string, value: (data: T) => number): CifWriter.Field<number, T> {
+    return CifWriter.Field.int(name, (i, d) => value(d));
 }
 
-function float64<T>(name: string, value: (data: T) => number, digitCount: number = 6): FieldDesc<T> {
-    return CIFField.float(name, (i, d) => value(d), { digitCount: digitCount, typedArray: Float64Array });
+function float64<T>(name: string, value: (data: T) => number, digitCount: number = 6): CifWriter.Field<number, T> {
+    return CifWriter.Field.float(name, (i, d) => value(d), { digitCount: digitCount, typedArray: Float64Array });
 }
 
 interface _vd3d_Ctx {
@@ -52,7 +50,7 @@ interface _vd3d_Ctx {
     sampledValuesInfo: DataFormat.ValuesInfo,
 }
 
-const _volume_data_3d_info_fields: FieldDesc<_vd3d_Ctx>[] = [
+const _volume_data_3d_info_fields = [
     string<_vd3d_Ctx>('name', ctx => ctx.header.channels[ctx.channelIndex]),
 
     int32<_vd3d_Ctx>('axis_order[0]', ctx => ctx.header.axisOrder[0]),
@@ -92,7 +90,7 @@ const _volume_data_3d_info_fields: FieldDesc<_vd3d_Ctx>[] = [
     float64<_vd3d_Ctx>('max_sampled', ctx => ctx.sampledValuesInfo.max)
 ];
 
-function _volume_data_3d_info(result: ResultContext): CIFCategory {
+function _volume_data_3d_info(result: ResultContext): CifWriter.Category {
     const ctx: _vd3d_Ctx = {
         header: result.query.data.header,
         channelIndex: result.channelIndex,
@@ -137,8 +135,7 @@ function _volume_data_3d(ctx: ResultContext) {
         encoder = E.by(E.byteArray)
     }
 
-    const fields: FieldDesc<typeof data>[] = [CIFField.float('values', _volume_data_3d_number, { encoder, typedArray, digitCount: 6 })]
-
+    const fields = [CifWriter.Field.float('values', _volume_data_3d_number, { encoder, typedArray, digitCount: 6 })];
     return { data, name: 'volume_data_3d', fields, rowCount: data.length };
 }
 
@@ -156,7 +153,7 @@ function queryBoxDimension(e: 'a' | 'b', d: number) {
     return string<Data.QueryContext>(`query_box_${e}[${d}]`, ctx => pickQueryBoxDimension(ctx, e, d), ctx => ctx.params.box.kind !== 'Cell');
 }
 
-const _density_server_result_fields: FieldDesc<Data.QueryContext>[] = [
+const _density_server_result_fields = [
     string<Data.QueryContext>('server_version', ctx => VERSION),
     string<Data.QueryContext>('datetime_utc', ctx => new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '')),
     string<Data.QueryContext>('guid', ctx => ctx.guid),
@@ -174,7 +171,7 @@ const _density_server_result_fields: FieldDesc<Data.QueryContext>[] = [
     queryBoxDimension('b', 2)
 ]
 
-function _density_server_result(ctx: Data.QueryContext): CIFCategory {
+function _density_server_result(ctx: Data.QueryContext): CifWriter.Category {
     return {
         data: ctx,
         name: 'density_server_result',
@@ -183,7 +180,7 @@ function _density_server_result(ctx: Data.QueryContext): CIFCategory {
     };
 }
 
-function write(encoder: CIFEncoder, query: Data.QueryContext) {
+function write(encoder: CifWriter.Encoder, query: Data.QueryContext) {
     encoder.startDataBlock('SERVER');
     encoder.writeCategory(_density_server_result, [query]);