Browse Source

wip, mmCIF exporter

David Sehnal 6 years ago
parent
commit
53c12b748c

+ 8 - 4
src/mol-io/writer/cif/encoder.ts

@@ -21,7 +21,7 @@ import { ArrayEncoder, ArrayEncoding } from '../../common/binary-cif';
 export interface Field<Key = any, Data = any> {
     name: string,
     type: Field.Type,
-    value(key: Key, data: Data): string | number
+    value(key: Key, data: Data, index: number): string | number
     valueKind?: (key: Key, data: Data) => Column.ValueKind,
     defaultFormat?: Field.Format,
     shouldInclude?: (data: Data) => boolean
@@ -38,11 +38,11 @@ export namespace Field {
 
     export type ParamsBase<K, D> = { valueKind?: (k: K, d: D) => Column.ValueKind, encoder?: ArrayEncoder, shouldInclude?: (data: D) => boolean }
 
-    export function str<K, D = any>(name: string, value: (k: K, d: D) => string, params?: ParamsBase<K, D>): Field<K, D> {
+    export function str<K, D = any>(name: string, value: (k: K, d: D, index: number) => string, params?: ParamsBase<K, D>): Field<K, D> {
         return { name, type: Type.Str, value, valueKind: params && params.valueKind, defaultFormat: params && params.encoder ? { encoder: params.encoder } : void 0, shouldInclude: params && params.shouldInclude };
     }
 
-    export function int<K, D = any>(name: string, value: (k: K, d: D) => number, params?:  ParamsBase<K, D> & { typedArray?: ArrayEncoding.TypedArrayCtor }): Field<K, D> {
+    export function int<K, D = any>(name: string, value: (k: K, d: D, index: number) => number, params?:  ParamsBase<K, D> & { typedArray?: ArrayEncoding.TypedArrayCtor }): Field<K, D> {
         return {
             name,
             type: Type.Int,
@@ -53,7 +53,7 @@ export namespace Field {
         };
     }
 
-    export function float<K, D = any>(name: string, value: (k: K, d: D) => number, params?: ParamsBase<K, D> & { typedArray?: ArrayEncoding.TypedArrayCtor, digitCount?: number }): Field<K, D> {
+    export function float<K, D = any>(name: string, value: (k: K, d: D, index: number) => number, params?: ParamsBase<K, D> & { typedArray?: ArrayEncoding.TypedArrayCtor, digitCount?: number }): Field<K, D> {
         return {
             name,
             type: Type.Float,
@@ -63,6 +63,10 @@ export namespace Field {
             shouldInclude: params && params.shouldInclude
         };
     }
+
+    export function index(name: string) {
+        return int(name, (e, d, i) => i + 1, { typedArray: Int32Array, encoder: ArrayEncoding.by(ArrayEncoding.delta).and(ArrayEncoding.runLength).and(ArrayEncoding.integerPacking) })
+    }
 }
 
 export interface Category<Key = any, Data = any> {

+ 1 - 1
src/mol-io/writer/cif/encoder/binary.ts

@@ -141,7 +141,7 @@ function encodeField(field: Field, data: { data: any, keys: () => Iterator<any>
                 allPresent = false;
             } else {
                 mask[offset] = Column.ValueKind.Present;
-                array[offset] = getter(key, d);
+                array[offset] = getter(key, d, offset);
             }
             offset++;
         }

+ 6 - 4
src/mol-io/writer/cif/encoder/text.ts

@@ -73,14 +73,14 @@ export default class TextEncoder implements Encoder<string> {
     }
 }
 
-function writeValue(builder: StringBuilder, data: any, key: any, f: Field<any, any>, floatPrecision: number): boolean {
+function writeValue(builder: StringBuilder, data: any, key: any, f: Field<any, any>, floatPrecision: number, index: number): boolean {
     const kind = f.valueKind;
     const p = kind ? kind(key, data) : Column.ValueKind.Present;
     if (p !== Column.ValueKind.Present) {
         if (p === Column.ValueKind.NotPresent) writeNotPresent(builder);
         else writeUnknown(builder);
     } else {
-        const val = f.value(key, data);
+        const val = f.value(key, data, index);
         const t = f.type;
         if (t === Field.Type.Str) {
             if (isMultiline(val as string)) {
@@ -127,7 +127,7 @@ function writeCifSingleRecord(category: Category<any>, builder: StringBuilder, f
         if (!filter.includeField(category.name, f.name)) continue;
 
         StringBuilder.writePadRight(builder, `_${category.name}.${f.name}`, width);
-        const multiline = writeValue(builder, data, key, f, precisions[_f]);
+        const multiline = writeValue(builder, data, key, f, precisions[_f], 0);
         if (!multiline) StringBuilder.newline(builder);
     }
     StringBuilder.write(builder, '#\n');
@@ -147,6 +147,7 @@ function writeCifLoop(categories: Category[], builder: StringBuilder, filter: Ca
         writeLine(builder, `_${first.name}.${fields[i].name}`);
     }
 
+    let index = 0;
     for (let _c = 0; _c < categories.length; _c++) {
         const category = categories[_c];
         const data = category.data;
@@ -159,9 +160,10 @@ function writeCifLoop(categories: Category[], builder: StringBuilder, filter: Ca
 
             let multiline = false;
             for (let _f = 0; _f < fieldCount; _f++) {
-                multiline = writeValue(builder, data, key, fields[_f], precisions[_f]);
+                multiline = writeValue(builder, data, key, fields[_f], precisions[_f], index);
             }
             if (!multiline) StringBuilder.newline(builder);
+            index++;
         }
     }
     StringBuilder.write(builder, '#\n');

+ 1 - 1
src/mol-model/structure/export/categories/atom_site.ts

@@ -14,7 +14,7 @@ import E = CifWriter.Encodings
 
 const atom_site_fields: CifField<Element.Location>[] = [
     CifField.str('group_PDB', P.residue.group_PDB),
-    CifField.int('id', P.atom.id, { encoder: E.deltaRLE }),
+    CifField.index('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),

+ 6 - 1
src/mol-model/structure/export/mmcif.ts

@@ -35,10 +35,15 @@ function _entity({ model, structure }: CifExportContext): CifCategory {
 const Categories = [
     copy_mmCif_category('entry'),
     copy_mmCif_category('exptl'),
+    _entity,
     copy_mmCif_category('cell'),
     copy_mmCif_category('symmetry'),
+    copy_mmCif_category('pdbx_struct_assembly'),
+    copy_mmCif_category('pdbx_struct_assembly_gen'),
+    copy_mmCif_category('pdbx_struct_oper_list'),
+    // TODO: filter for actual present residues?
     copy_mmCif_category('chem_comp'),
-    _entity,
+    copy_mmCif_category('atom_sites'),
     _atom_site
 ];