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

Conditional inclusion in CIF writer fields

parent e3f49b61
No related branches found
No related tags found
No related merge requests found
......@@ -21,9 +21,10 @@ 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
valueKind?: (key: Key, data: Data) => Column.ValueKind,
defaultFormat?: Field.Format,
value(key: Key, data: Data): string | number
shouldInclude?: (data: Data) => boolean
}
export namespace Field {
......@@ -35,31 +36,31 @@ export namespace Field {
typedArray?: ArrayEncoding.TypedArrayCtor
}
export function getDigitCount(field: Field) {
if (field.defaultFormat && typeof field.defaultFormat.digitCount !== 'undefined') return Math.max(0, Math.min(field.defaultFormat.digitCount, 16));
return 6;
}
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?: { valueKind?: (k: K, d: D) => Column.ValueKind, encoder?: ArrayEncoder }): Field<K, D> {
return { name, type: Type.Str, value, valueKind: params && params.valueKind, defaultFormat: params && params.encoder ? { encoder: params.encoder } : void 0 };
export function str<K, D = any>(name: string, value: (k: K, d: D) => 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?: { valueKind?: (k: K, d: D) => Column.ValueKind, encoder?: ArrayEncoder, typedArray?: ArrayEncoding.TypedArrayCtor }): Field<K, D> {
export function int<K, D = any>(name: string, value: (k: K, d: D) => number, params?: ParamsBase<K, D> & { typedArray?: ArrayEncoding.TypedArrayCtor }): Field<K, D> {
return {
name,
type: Type.Int,
value,
valueKind: params && params.valueKind,
defaultFormat: params ? { encoder: params.encoder, typedArray: params.typedArray } : void 0 };
defaultFormat: params ? { encoder: params.encoder, typedArray: params.typedArray } : void 0,
shouldInclude: params && params.shouldInclude
};
}
export function float<K, D = any>(name: string, value: (k: K, d: D) => number, params?: { valueKind?: (k: K, d: D) => Column.ValueKind, encoder?: ArrayEncoder, typedArray?: ArrayEncoding.TypedArrayCtor, digitCount?: number }): Field<K, D> {
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> {
return {
name,
type: Type.Float,
value,
valueKind: params && params.valueKind,
defaultFormat: params ? { encoder: params.encoder, typedArray: params.typedArray, digitCount: typeof params.digitCount !== 'undefined' ? params.digitCount : void 0 } : void 0
defaultFormat: params ? { encoder: params.encoder, typedArray: params.typedArray, digitCount: typeof params.digitCount !== 'undefined' ? params.digitCount : void 0 } : void 0,
shouldInclude: params && params.shouldInclude
};
}
}
......
......@@ -14,6 +14,7 @@ import {
} from '../../../common/binary-cif'
import { Field, Category, Encoder } from '../encoder'
import Writer from '../../writer'
import { getIncludedFields } from './util';
export default class BinaryEncoder implements Encoder<Uint8Array> {
private data: EncodedFile;
......@@ -57,12 +58,17 @@ export default class BinaryEncoder implements Encoder<Uint8Array> {
const first = categories[0]!;
const cat: EncodedCategory = { name: '_' + first.name, columns: [], rowCount: count };
const data = categories.map(c => ({ data: c.data, keys: () => c.keys ? c.keys() : Iterator.Range(0, c.rowCount - 1) }));
for (const f of first.fields) {
const fields = getIncludedFields(first);
for (const f of fields) {
if (!this.filter.includeField(first.name, f.name)) continue;
const format = this.formatter.getFormat(first.name, f.name);
cat.columns.push(encodeField(f, data, count, getArrayCtor(f, format), getEncoder(f, format)));
}
// no columns included.
if (!cat.columns.length) return;
this.dataBlocks[this.dataBlocks.length - 1].categories.push(cat);
}
......
......@@ -11,6 +11,7 @@ import { Column } from 'mol-data/db'
import StringBuilder from 'mol-util/string-builder'
import { Category, Field, Encoder } from '../encoder'
import Writer from '../../writer'
import { getFieldDigitCount, getIncludedFields } from './util';
export default class TextEncoder implements Encoder<string> {
private builder = StringBuilder.create();
......@@ -102,13 +103,13 @@ function getFloatPrecisions(categoryName: string, fields: Field[], formatter: Ca
for (const f of fields) {
const format = formatter.getFormat(categoryName, f.name);
if (format && typeof format.digitCount !== 'undefined') ret[ret.length] = f.type === Field.Type.Float ? Math.pow(10, Math.max(0, Math.min(format.digitCount, 15))) : 0;
else ret[ret.length] = f.type === Field.Type.Float ? Math.pow(10, Field.getDigitCount(f)) : 0;
else ret[ret.length] = f.type === Field.Type.Float ? Math.pow(10, getFieldDigitCount(f)) : 0;
}
return ret;
}
function writeCifSingleRecord(category: Category<any>, builder: StringBuilder, filter: Category.Filter, formatter: Category.Formatter) {
const fields = category.fields;
const fields = getIncludedFields(category);
const data = category.data;
let width = fields.reduce((w, f) => filter.includeField(category.name, f.name) ? Math.max(w, f.name.length) : 0, 0);
......@@ -134,8 +135,11 @@ function writeCifSingleRecord(category: Category<any>, builder: StringBuilder, f
function writeCifLoop(categories: Category[], builder: StringBuilder, filter: Category.Filter, formatter: Category.Formatter) {
const first = categories[0];
const fields = filter === Category.DefaultFilter ? first.fields : first.fields.filter(f => filter.includeField(first.name, f.name));
const fieldSource = getIncludedFields(first);
const fields = filter === Category.DefaultFilter ? fieldSource : fieldSource.filter(f => filter.includeField(first.name, f.name));
const fieldCount = fields.length;
if (fieldCount === 0) return;
const precisions = getFloatPrecisions(first.name, fields, formatter);
writeLine(builder, 'loop_');
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Field, Category } from '../encoder';
export function getFieldDigitCount(field: Field) {
if (field.defaultFormat && typeof field.defaultFormat.digitCount !== 'undefined') return Math.max(0, Math.min(field.defaultFormat.digitCount, 16));
return 6;
}
export function getIncludedFields(category: Category<any, any>) {
return category.fields.some(f => !!f.shouldInclude)
? category.fields.filter(f => !f.shouldInclude || f.shouldInclude(category.data))
: category.fields;
}
\ No newline at end of file
......@@ -18,7 +18,7 @@ interface SymmetryOperator {
}
namespace SymmetryOperator {
export const DefaultName = 'identity'
export const DefaultName = '1_555'
export const Default: SymmetryOperator = create(DefaultName, Mat4.identity());
const RotationEpsilon = 0.0001;
......
......@@ -47,7 +47,9 @@ const atom_site_fields: CifField<Element.Location>[] = [
CifField.str('auth_asym_id', P.chain.auth_asym_id),
CifField.int('pdbx_PDB_model_num', P.unit.model_num, { encoder: E.deltaRLE }),
CifField.str('operator_name', P.unit.operator_name)
CifField.str<Element.Location, Structure>('operator_name', P.unit.operator_name, {
shouldInclude: structure => structure.units.some(u => !u.conformation.operator.isIdentity)
})
];
function copy_mmCif_cat(name: keyof mmCIF_Schema) {
......@@ -66,7 +68,7 @@ function _entity({ model, structure }: Context): CifCategory {
function _atom_site({ structure }: Context): CifCategory {
return {
data: void 0,
data: structure,
name: 'atom_site',
fields: atom_site_fields,
rowCount: structure.elementCount,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment