Skip to content
Snippets Groups Projects
Commit 53c12b74 authored by David Sehnal's avatar David Sehnal
Browse files

wip, mmCIF exporter

parent 5c73fd87
No related branches found
No related tags found
No related merge requests found
......@@ -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> {
......
......@@ -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++;
}
......
......@@ -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');
......
......@@ -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),
......
......@@ -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
];
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment