Skip to content
Snippets Groups Projects
Commit 1e1a3da0 authored by Alexander Rose's avatar Alexander Rose
Browse files

Merge branch 'master' into custom-repr

parents 84e6ebf5 da051fd1
Branches
Tags
No related merge requests found
Showing
with 501 additions and 28 deletions
File suppressed by a .gitattributes entry, the file's encoding is unsupported, or the file size exceeds the limit.
......@@ -117,7 +117,7 @@ export function getCifFieldType(field: CifField): Column.Schema.Int | Column.Sch
let floatCount = 0, hasString = false;
for (let i = 0, _i = field.rowCount; i < _i; i++) {
const k = field.valueKind(i);
if (k !== Column.ValueKind.Present) continue
if (k !== Column.ValueKind.Present) continue;
const type = getNumberType(field.str(i));
if (type === NumberType.Int) continue;
else if (type === NumberType.Float) floatCount++;
......
......@@ -128,5 +128,5 @@ export function getNumberType(str: string): NumberType {
}
else break;
}
return NumberType.Int;
return start === end ? NumberType.Int : NumberType.NaN;
}
......@@ -4,10 +4,10 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import Matrix from './matrix.js';
import { Vec3 } from '../3d.js';
import Matrix from './matrix';
import { Vec3 } from '../3d';
// import { Vec3, Mat4 } from '../3d.js';
import { svd } from './svd.js';
import { svd } from './svd';
// const negateVector = Vec3.create(-1, -1, -1)
// const tmpMatrix = Mat4.identity()
......
......@@ -20,6 +20,12 @@ export interface CifExportContext {
cache: any
}
export namespace CifExportContext {
export function create(structure: Structure, model: Model): CifExportContext {
return { structure, model, cache: Object.create(null) };
}
}
function copy_mmCif_category(name: keyof mmCIF_Schema): CifCategory<CifExportContext> {
return {
name,
......@@ -87,14 +93,17 @@ export const mmCIF_Export_Filters = {
}
/** Doesn't start a data block */
export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: Structure) {
export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: Structure, params?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext }) {
const models = structure.models;
if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.';
const model = models[0];
const ctx: CifExportContext[] = [{ structure, model, cache: Object.create(null) }];
const _params = params || { };
const ctx: CifExportContext[] = [_params.exportCtx ? _params.exportCtx : CifExportContext.create(structure, model)];
for (const cat of Categories) {
if (_params.skipCategoryNames && _params.skipCategoryNames.has(cat.name)) continue;
encoder.writeCategory(cat, ctx);
}
for (const customProp of model.customProperties.all) {
......@@ -103,6 +112,7 @@ export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: S
const prefix = customProp.cifExport.prefix;
const cats = customProp.cifExport.categories;
for (const cat of cats) {
if (_params.skipCategoryNames && _params.skipCategoryNames.has(cat.name)) continue;
if (cat.name.indexOf(prefix) !== 0) throw new Error(`Custom category '${cat.name}' name must start with prefix '${prefix}.'`);
encoder.writeCategory(cat, ctx);
}
......
......@@ -30,7 +30,7 @@ export class QueryContext implements QueryContextView {
currentStructure: Structure = void 0 as any;
/** Current link between atoms */
readonly atomicLink: Link.Location<Unit.Atomic> = void 0 as any;
readonly atomicLink: Link.Location<Unit.Atomic> = Link.Location() as Link.Location<Unit.Atomic>;
setElement(unit: Unit, e: ElementIndex) {
this.element.unit = unit;
......
......@@ -12,6 +12,9 @@ import { StructureSelection } from '../selection';
import { structureAreIntersecting } from '../utils/structure-set';
import { Vec3 } from 'mol-math/linear-algebra';
import { checkStructureMaxRadiusDistance, checkStructureMinMaxDistance } from '../utils/structure-distance';
import Structure from '../../structure/structure';
import StructureElement from '../../structure/element';
import { SortedArray } from 'mol-data/int';
export function pick(query: StructureQuery, pred: QueryPredicate): StructureQuery {
return ctx => {
......@@ -205,5 +208,101 @@ function withinMinMaxRadius({ queryCtx, selection, target, minRadius, maxRadius,
return ret.getSelection();
}
interface IsConnectedToCtx {
queryCtx: QueryContext,
input: Structure,
target: Structure,
bondTest: QueryFn<boolean>,
tElement: StructureElement
}
function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
const { queryCtx, input, target, bondTest, tElement } = ctx;
const interLinks = input.links;
for (const unit of structure.units) {
if (!Unit.isAtomic(unit)) continue;
const inputUnit = input.unitMap.get(unit.id) as Unit.Atomic;
const { offset, b } = inputUnit.links;
const linkedUnits = interLinks.getLinkedUnits(unit);
const luCount = linkedUnits.length;
queryCtx.atomicLink.aUnit = inputUnit;
const srcElements = unit.elements;
const inputElements = inputUnit.elements;
for (let i = 0 as StructureElement.UnitIndex, _i = srcElements.length; i < _i; i++) {
const inputIndex = SortedArray.indexOf(inputElements, srcElements[i]) as StructureElement.UnitIndex;
// TODO: isConnectedTo
\ No newline at end of file
queryCtx.atomicLink.aIndex = inputIndex;
queryCtx.atomicLink.bUnit = inputUnit;
tElement.unit = unit;
for (let l = offset[inputIndex], _l = offset[inputIndex + 1]; l < _l; l++) {
tElement.element = inputElements[b[l]];
if (!target.hasElement(tElement)) continue;
queryCtx.atomicLink.bIndex = b[l] as StructureElement.UnitIndex;
if (bondTest(queryCtx)) return true;
}
for (let li = 0; li < luCount; li++) {
const lu = linkedUnits[li];
tElement.unit = lu.unitB;
queryCtx.atomicLink.bUnit = lu.unitB;
const bElements = lu.unitB.elements;
const bonds = lu.getBonds(inputIndex);
for (let bi = 0, _bi = bonds.length; bi < _bi; bi++) {
const bond = bonds[bi];
tElement.element = bElements[bond.indexB];
if (!target.hasElement(tElement)) continue;
queryCtx.atomicLink.bIndex = bond.indexB;
if (bondTest(queryCtx)) return true;
}
}
}
}
return false;
}
export interface IsConnectedToParams {
query: StructureQuery,
target: StructureQuery,
bondTest?: QueryFn<boolean>,
disjunct: boolean,
invert: boolean
}
function defaultBondTest(ctx: QueryContext) {
return true;
}
export function isConnectedTo({ query, target, disjunct, invert, bondTest }: IsConnectedToParams): StructureQuery {
return ctx => {
const targetSel = target(ctx);
if (StructureSelection.isEmpty(targetSel)) return targetSel;
const selection = query(ctx);
if (StructureSelection.isEmpty(selection)) return selection;
const connCtx: IsConnectedToCtx = {
queryCtx: ctx,
input: ctx.inputStructure,
target: StructureSelection.unionStructure(targetSel),
bondTest: bondTest || defaultBondTest,
tElement: StructureElement.create()
}
const ret = StructureSelection.LinearBuilder(ctx.inputStructure);
ctx.pushCurrentLink();
StructureSelection.forEach(selection, (s, sI) => {
if (checkConnected(connCtx, s)) ret.add(s);
if (sI % 5 === 0) ctx.throwIfTimedOut();
})
ctx.popCurrentLink();
return ret.getSelection();
}
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ import { QueryContext, QueryFn } from '../context';
import { structureIntersect, structureSubtract } from '../utils/structure-set';
import { UniqueArray } from 'mol-data/generic';
import { StructureSubsetBuilder } from '../../structure/util/subset-builder';
import StructureElement from '../../structure/element';
function getWholeResidues(ctx: QueryContext, source: Structure, structure: Structure) {
const builder = source.subsetBuilder(true);
......@@ -59,8 +60,7 @@ export function wholeResidues(query: StructureQuery): StructureQuery {
export interface IncludeSurroundingsParams {
radius: number,
// TODO
// atomRadius?: Element.Property<number>,
elementRadius?: QueryFn<number>,
wholeResidues?: boolean
}
......@@ -82,9 +82,88 @@ function getIncludeSurroundings(ctx: QueryContext, source: Structure, structure:
return !!params.wholeResidues ? getWholeResidues(ctx, source, builder.getStructure()) : builder.getStructure();
}
interface IncludeSurroundingsParamsWithRadius extends IncludeSurroundingsParams {
elementRadius: QueryFn<number>,
elementRadiusClosure: StructureElement.Property<number>,
sourceMaxRadius: number
}
function getIncludeSurroundingsWithRadius(ctx: QueryContext, source: Structure, structure: Structure, params: IncludeSurroundingsParamsWithRadius) {
const builder = new StructureUniqueSubsetBuilder(source);
const lookup = source.lookup3d;
const { elementRadius, elementRadiusClosure, sourceMaxRadius, radius } = params;
ctx.pushCurrentElement();
for (const unit of structure.units) {
ctx.element.unit = unit;
const { x, y, z } = unit.conformation;
const elements = unit.elements;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
ctx.element.element = e;
const eRadius = elementRadius(ctx);
lookup.findIntoBuilderWithRadius(x(e), y(e), z(e), eRadius, sourceMaxRadius, radius, elementRadiusClosure, builder);
}
ctx.throwIfTimedOut();
}
ctx.popCurrentElement();
return !!params.wholeResidues ? getWholeResidues(ctx, source, builder.getStructure()) : builder.getStructure();
}
function createElementRadiusFn(ctx: QueryContext, eRadius: QueryFn<number>): StructureElement.Property<number> {
return e => {
ctx.element.unit = e.unit;
ctx.element.element = e.element;
return eRadius(ctx);
}
}
function findStructureRadius(ctx: QueryContext, eRadius: QueryFn<number>) {
let r = 0;
for (const unit of ctx.inputStructure.units) {
ctx.element.unit = unit;
const elements = unit.elements;
for (let i = 0, _i = elements.length; i < _i; i++) {
const e = elements[i];
ctx.element.element = e;
const eR = eRadius(ctx);
if (eR > r) r = eR;
}
}
ctx.throwIfTimedOut();
return r;
}
export function includeSurroundings(query: StructureQuery, params: IncludeSurroundingsParams): StructureQuery {
return ctx => {
const inner = query(ctx);
if (params.elementRadius) {
const prms: IncludeSurroundingsParamsWithRadius = {
...params,
elementRadius: params.elementRadius,
elementRadiusClosure: createElementRadiusFn(ctx, params.elementRadius),
sourceMaxRadius: findStructureRadius(ctx, params.elementRadius)
};
if (StructureSelection.isSingleton(inner)) {
const surr = getIncludeSurroundingsWithRadius(ctx, ctx.inputStructure, inner.structure, prms);
const ret = StructureSelection.Singletons(ctx.inputStructure, surr);
return ret;
} else {
const builder = new UniqueStructuresBuilder(ctx.inputStructure);
for (const s of inner.structures) {
builder.add(getIncludeSurroundingsWithRadius(ctx, ctx.inputStructure, s, prms));
}
return builder.getSelection();
}
}
if (StructureSelection.isSingleton(inner)) {
const surr = getIncludeSurroundings(ctx, ctx.inputStructure, inner.structure, params);
const ret = StructureSelection.Singletons(ctx.inputStructure, surr);
......@@ -218,4 +297,86 @@ export function expandProperty(query: StructureQuery, property: QueryFn): Struct
};
}
// TODO: unionBy (skip this one?), cluster, includeConnected, includeSurroundings with "radii"
\ No newline at end of file
export interface IncludeConnectedParams {
query: StructureQuery,
bondTest?: QueryFn<boolean>,
layerCount: number,
wholeResidues: boolean
}
export function includeConnected({ query, layerCount, wholeResidues, bondTest }: IncludeConnectedParams): StructureQuery {
return ctx => {
return 0 as any;
}
}
// function defaultBondTest(ctx: QueryContext) {
// return true;
// }
// interface IncludeConnectedCtx {
// queryCtx: QueryContext,
// input: Structure,
// bondTest: QueryFn<boolean>,
// wholeResidues: boolean
// }
// type FrontierSet = UniqueArray<StructureElement.UnitIndex, StructureElement.UnitIndex>
// type Frontier = { unitIds: UniqueArray<number>, elements: Map<number /* unit id */, FrontierSet> }
// namespace Frontier {
// export function has({ elements }: Frontier, unitId: number, element: StructureElement.UnitIndex) {
// if (!elements.has(unitId)) return false;
// const xs = elements.get(unitId)!;
// return xs.keys.has(element);
// }
// export function create(pivot: Structure, input: Structure) {
// const unitIds = UniqueArray.create<number>();
// const elements: Frontier['elements'] = new Map();
// for (const unit of pivot.units) {
// if (!Unit.isAtomic(unit)) continue;
// UniqueArray.add(unitIds, unit.id, unit.id);
// const xs: FrontierSet = UniqueArray.create();
// elements.set(unit.id, xs);
// const pivotElements = unit.elements;
// const inputElements = input.unitMap.get(unit.id).elements;
// for (let i = 0, _i = pivotElements.length; i < _i; i++) {
// const idx = SortedArray.indexOf(inputElements, pivotElements[i]) as StructureElement.UnitIndex;
// UniqueArray.add(xs, idx, idx);
// }
// }
// return { unitIds, elements };
// }
// export function addFrontier(target: Frontier, from: Frontier) {
// for (const unitId of from.unitIds.array) {
// let xs: FrontierSet;
// if (target.elements.has(unitId)) {
// xs = target.elements.get(unitId)!;
// } else {
// xs = UniqueArray.create();
// target.elements.set(unitId, xs);
// UniqueArray.add(target.unitIds, unitId, unitId);
// }
// for (const e of from.elements.get(unitId)!.array) {
// UniqueArray.add(xs, e, e);
// }
// }
// return target;
// }
// export function includeWholeResidues(structure: Structure, frontier: Frontier) {
// // ...
// }
// }
// function expandFrontier(ctx: IncludeConnectedCtx, currentFrontier: Frontier, result: Frontier): Frontier {
// return 0 as any;
// }
// TODO: unionBy (skip this one?), cluster
\ No newline at end of file
......@@ -114,6 +114,11 @@ class Structure {
return this._props.models;
}
hasElement(e: StructureElement) {
if (!this.unitMap.has(e.unit.id)) return false;
return SortedArray.has(this.unitMap.get(e.unit.id).elements, e.element);
}
constructor(units: ArrayLike<Unit>) {
const map = IntMap.Mutable<Unit>();
let elementCount = 0;
......
......@@ -73,11 +73,11 @@ class InterUnitBonds {
namespace InterUnitBonds {
export class UnitPairBonds {
hasBonds(indexA: number) {
hasBonds(indexA: StructureElement.UnitIndex) {
return this.linkMap.has(indexA);
}
getBonds(indexA: number): ReadonlyArray<InterUnitBonds.BondInfo> {
getBonds(indexA: StructureElement.UnitIndex): ReadonlyArray<InterUnitBonds.BondInfo> {
if (!this.linkMap.has(indexA)) return emptyArray;
return this.linkMap.get(indexA)!;
}
......
......@@ -10,6 +10,7 @@ import { Vec3 } from 'mol-math/linear-algebra';
import { computeStructureBoundary } from './boundary';
import { OrderedSet } from 'mol-data/int';
import { StructureUniqueSubsetBuilder } from './unique-subset-builder';
import StructureElement from '../element';
export class StructureLookup3D {
private unitLookup: Lookup3D;
......@@ -66,6 +67,39 @@ export class StructureLookup3D {
}
}
findIntoBuilderWithRadius(x: number, y: number, z: number, pivotR: number, maxRadius: number, radius: number, eRadius: StructureElement.Property<number>, builder: StructureUniqueSubsetBuilder) {
const { units } = this.structure;
const closeUnits = this.unitLookup.find(x, y, z, radius);
if (closeUnits.count === 0) return;
const se = StructureElement.create();
const queryRadius = pivotR + maxRadius + radius;
for (let t = 0, _t = closeUnits.count; t < _t; t++) {
const unit = units[closeUnits.indices[t]];
Vec3.set(this.pivot, x, y, z);
if (!unit.conformation.operator.isIdentity) {
Vec3.transformMat4(this.pivot, this.pivot, unit.conformation.operator.inverse);
}
const unitLookup = unit.lookup3d;
const groupResult = unitLookup.find(this.pivot[0], this.pivot[1], this.pivot[2], queryRadius);
if (groupResult.count === 0) continue;
const elements = unit.elements;
se.unit = unit;
builder.beginUnit(unit.id);
for (let j = 0, _j = groupResult.count; j < _j; j++) {
se.element = elements[groupResult.indices[j]];
const rr = eRadius(se);
if (Math.sqrt(groupResult.squaredDistances[j]) - pivotR - rr > radius) continue;
builder.addElement(elements[groupResult.indices[j]]);
}
builder.commitUnit();
}
}
check(x: number, y: number, z: number, radius: number): boolean {
const { units } = this.structure;
const closeUnits = this.unitLookup.find(x, y, z, radius);
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import * as argparse from 'argparse'
import { preprocessFile } from './preprocess/preprocess';
const cmdParser = new argparse.ArgumentParser({
addHelp: true,
description: 'Preprocess CIF files to include custom properties and convert them to BinaryCIF format.'
});
cmdParser.addArgument(['--input', '-i'], { help: 'Input filename', required: true });
cmdParser.addArgument(['--outCIF', '-oc'], { help: 'Output CIF filename', required: false });
cmdParser.addArgument(['--outBCIF', '-ob'], { help: 'Output BinaryCIF filename', required: false });
// TODO: "bulk" mode
interface CmdArgs {
input: string,
outCIF?: string,
outBCIF?: string
}
const cmdArgs = cmdParser.parseArgs() as CmdArgs;
if (cmdArgs.input) preprocessFile(cmdArgs.input, cmdArgs.outCIF, cmdArgs.outBCIF);
// example:
// node build\node_modules\servers\model\preprocess -i e:\test\Quick\1cbs_updated.cif -oc e:\test\mol-star\model\1cbs.cif -ob e:\test\mol-star\model\1cbs.bcif
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { CifCategory, CifField, CifFrame, getCifFieldType } from 'mol-io/reader/cif';
import { CifWriter } from 'mol-io/writer/cif';
import { Task } from 'mol-task';
import { showProgress } from './util';
function getCategoryInstanceProvider(cat: CifCategory, fields: CifWriter.Field[]): CifWriter.Category {
return {
name: cat.name,
instance: () => ({ data: cat, fields, rowCount: cat.rowCount })
};
}
function classify(name: string, field: CifField): CifWriter.Field {
const type = getCifFieldType(field);
if (type['@type'] === 'str') {
return { name, type: CifWriter.Field.Type.Str, value: field.str, valueKind: field.valueKind };
} else if (type['@type'] === 'float') {
return CifWriter.Field.float(name, field.float, { valueKind: field.valueKind, typedArray: Float64Array });
} else {
return CifWriter.Field.int(name, field.int, { valueKind: field.valueKind, typedArray: Int32Array });
}
}
export function classifyCif(frame: CifFrame) {
return Task.create('Classify CIF Data', async ctx => {
let maxProgress = 0;
for (const c of frame.categoryNames) maxProgress += frame.categories[c].fieldNames.length;
const ret: CifWriter.Category[] = [];
let current = 0;
for (const c of frame.categoryNames) {
const cat = frame.categories[c];
const fields: CifWriter.Field[] = [];
for (const f of cat.fieldNames) {
const cifField = classify(f, cat.getField(f)!);
fields.push(cifField);
current++;
if (ctx.shouldUpdate) await ctx.update({ message: 'Classifying...', current, max: maxProgress });
}
ret.push(getCategoryInstanceProvider(cat, fields));
}
return ret;
}).run(showProgress, 250);
}
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { readStructure } from '../server/structure-wrapper';
import { classifyCif } from './converter';
import { ConsoleLogger } from 'mol-util/console-logger';
import { Structure } from 'mol-model/structure';
import { CifWriter } from 'mol-io/writer/cif';
import Writer from 'mol-io/writer/writer';
import { wrapFileToWriter } from '../server/api-local';
import { Task } from 'mol-task';
import { showProgress, clearLine } from './util';
import { encode_mmCIF_categories, CifExportContext } from 'mol-model/structure/export/mmcif';
// TODO: error handling, bulk mode
export async function preprocessFile(filename: string, outputCif?: string, outputBcif?: string) {
ConsoleLogger.log('ModelServer', `Reading ${filename}...`);
const input = await readStructure('entry', '_local_', filename);
ConsoleLogger.log('ModelServer', `Classifying CIF categories...`);
const categories = await classifyCif(input.cifFrame);
clearLine();
const exportCtx = CifExportContext.create(input.structure, input.structure.models[0]);
if (outputCif) {
ConsoleLogger.log('ModelServer', `Encoding CIF...`);
const writer = wrapFileToWriter(outputCif);
const encoder = CifWriter.createEncoder({ binary: false });
await encode(input.structure, input.cifFrame.header, categories, encoder, exportCtx, writer);
clearLine();
writer.end();
}
if (outputBcif) {
ConsoleLogger.log('ModelServer', `Encoding BinaryCIF...`);
const writer = wrapFileToWriter(outputBcif);
const encoder = CifWriter.createEncoder({ binary: true, binaryAutoClassifyEncoding: true });
await encode(input.structure, input.cifFrame.header, categories, encoder, exportCtx, writer);
clearLine();
writer.end();
}
ConsoleLogger.log('ModelServer', `Done.`);
}
function encode(structure: Structure, header: string, categories: CifWriter.Category[], encoder: CifWriter.Encoder, exportCtx: CifExportContext, writer: Writer) {
return Task.create('Encode', async ctx => {
const skipCategoryNames = new Set<string>(categories.map(c => c.name));
encoder.startDataBlock(header);
let current = 0;
for (const cat of categories){
encoder.writeCategory(cat);
current++;
if (ctx.shouldUpdate) await ctx.update({ message: 'Encoding...', current, max: categories.length });
}
encode_mmCIF_categories(encoder, structure, { skipCategoryNames, exportCtx });
encoder.encode();
encoder.writeTo(writer);
}).run(showProgress, 250);
}
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Progress } from 'mol-task';
export function showProgress(p: Progress) {
process.stdout.write(`\r${new Array(80).join(' ')}`);
process.stdout.write(`\r${Progress.format(p)}`);
}
export function clearLine() {
process.stdout.write(`\r${new Array(80).join(' ')}`);
process.stdout.write(`\r`);
}
\ No newline at end of file
......@@ -39,7 +39,7 @@ export async function runLocal(input: LocalInput) {
while (job) {
try {
const encoder = await resolveJob(job);
const writer = wrapFile(job.outputFilename!);
const writer = wrapFileToWriter(job.outputFilename!);
encoder.writeTo(writer);
writer.end();
ConsoleLogger.logId(job.id, 'Query', 'Written.');
......@@ -61,7 +61,7 @@ export async function runLocal(input: LocalInput) {
StructureCache.expireAll();
}
function wrapFile(fn: string) {
export function wrapFileToWriter(fn: string) {
const w = {
open(this: any) {
if (this.opened) return;
......@@ -71,7 +71,7 @@ function wrapFile(fn: string) {
},
writeBinary(this: any, data: Uint8Array) {
this.open();
fs.writeSync(this.file, new Buffer(data));
fs.writeSync(this.file, new Buffer(data.buffer));
return true;
},
writeString(this: any, data: string) {
......
......@@ -8,7 +8,7 @@ import { Structure, Model, Format } from 'mol-model/structure';
import { PerformanceMonitor } from 'mol-util/performance-monitor';
import { Cache } from './cache';
import Config from '../config';
import CIF from 'mol-io/reader/cif'
import CIF, { CifFrame } from 'mol-io/reader/cif'
import * as util from 'util'
import * as fs from 'fs'
import * as zlib from 'zlib'
......@@ -34,21 +34,22 @@ export interface StructureInfo {
entryId: string
}
export class StructureWrapper {
info: StructureInfo;
export interface StructureWrapper {
info: StructureInfo,
key: string;
approximateSize: number;
structure: Structure;
key: string,
approximateSize: number,
structure: Structure,
cifFrame: CifFrame
}
export async function getStructure(job: Job): Promise<StructureWrapper> {
if (Config.cacheParams.useCache) {
export async function getStructure(job: Job, allowCache = true): Promise<StructureWrapper> {
if (allowCache && Config.cacheParams.useCache) {
const ret = StructureCache.get(job.key);
if (ret) return ret;
}
const ret = await readStructure(job.key, job.sourceId, job.entryId);
if (Config.cacheParams.useCache) {
if (allowCache && Config.cacheParams.useCache) {
StructureCache.add(ret);
}
return ret;
......@@ -84,7 +85,7 @@ async function parseCif(data: string|Uint8Array) {
return parsed.result;
}
async function readStructure(key: string, sourceId: string, entryId: string) {
export async function readStructure(key: string, sourceId: string | '_local_', entryId: string) {
const filename = sourceId === '_local_' ? entryId : Config.mapFile(sourceId, entryId);
if (!filename) throw new Error(`Cound not map '${key}' to a valid filename.`);
if (!fs.existsSync(filename)) throw new Error(`Could not find source file for '${key}'.`);
......@@ -127,7 +128,8 @@ async function readStructure(key: string, sourceId: string, entryId: string) {
},
key,
approximateSize: typeof data === 'string' ? 2 * data.length : data.length,
structure
structure,
cifFrame: frame
};
return ret;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment