From 4ba3a5c811a606cebe8426f50ff61fcd52dc4810 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Mon, 24 Sep 2018 10:55:18 +0200 Subject: [PATCH] wip ModelServer multiple model support --- src/servers/model/preprocess/preprocess.ts | 11 +++-- src/servers/model/server/query.ts | 10 ++-- src/servers/model/server/structure-wrapper.ts | 46 +++++++++++++++---- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/servers/model/preprocess/preprocess.ts b/src/servers/model/preprocess/preprocess.ts index cf45825df..f54468091 100644 --- a/src/servers/model/preprocess/preprocess.ts +++ b/src/servers/model/preprocess/preprocess.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { readStructure } from '../server/structure-wrapper'; +import { readStructureWrapper, resolveStructure } from '../server/structure-wrapper'; import { classifyCif } from './converter'; // import { ConsoleLogger } from 'mol-util/console-logger'; import { Structure } from 'mol-model/structure'; @@ -24,18 +24,19 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu //const started = now(); //ConsoleLogger.log(`${linearId}`, `Reading '${filename}'...`); // TODO: support the custom prop provider list here. - const input = await readStructure('entry', '_local_', filename, void 0); + const input = await readStructureWrapper('entry', '_local_', filename, void 0); + const inputStructure = (await resolveStructure(input))!; //ConsoleLogger.log(`${linearId}`, `Classifying CIF categories...`); const categories = await classifyCif(input.cifFrame); //clearLine(); - const exportCtx = CifExportContext.create(input.structure, input.structure.models[0]); + const exportCtx = CifExportContext.create(inputStructure, inputStructure.models[0]); if (outputCif) { //ConsoleLogger.log(`${linearId}`, `Encoding CIF...`); const writer = wrapFileToWriter(outputCif); const encoder = CifWriter.createEncoder({ binary: false }); - await encode(input.structure, input.cifFrame.header, categories, encoder, exportCtx, writer); + await encode(inputStructure, input.cifFrame.header, categories, encoder, exportCtx, writer); // clearLine(); writer.end(); } @@ -44,7 +45,7 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu // ConsoleLogger.log(`${linearId}`, `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); + await encode(inputStructure, input.cifFrame.header, categories, encoder, exportCtx, writer); //clearLine(); writer.end(); } diff --git a/src/servers/model/server/query.ts b/src/servers/model/server/query.ts index f4b699b99..50c04e0c9 100644 --- a/src/servers/model/server/query.ts +++ b/src/servers/model/server/query.ts @@ -14,7 +14,7 @@ import { PerformanceMonitor } from 'mol-util/performance-monitor'; import Config from '../config'; import Version from '../version'; import { Job } from './jobs'; -import { getStructure, StructureWrapper } from './structure-wrapper'; +import { createStructureWrapperFromJob, StructureWrapper, resolveStructure } from './structure-wrapper'; import CifField = CifWriter.Field import { createModelPropertiesProviderFromConfig } from '../provider'; @@ -31,13 +31,15 @@ const propertyProvider = createModelPropertiesProviderFromConfig(); export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> { ConsoleLogger.logId(job.id, 'Query', 'Starting.'); - const wrappedStructure = await getStructure(job, propertyProvider); + const wrappedStructure = await createStructureWrapperFromJob(job, propertyProvider); try { perf.start('query'); + const sourceStructure = await resolveStructure(wrappedStructure); + if (!sourceStructure) throw new Error('Model not available'); const structure = job.queryDefinition.structureTransform - ? await job.queryDefinition.structureTransform(job.normalizedParams, wrappedStructure.structure) - : wrappedStructure.structure; + ? await job.queryDefinition.structureTransform(job.normalizedParams, sourceStructure) + : sourceStructure; const query = job.queryDefinition.query(job.normalizedParams, structure); const result = await StructureSelection.unionStructure(StructureQuery.run(query, structure, Config.maxQueryTimeInMs)); perf.end('query'); diff --git a/src/servers/model/server/structure-wrapper.ts b/src/servers/model/server/structure-wrapper.ts index cf3506a13..d7ffc7f2d 100644 --- a/src/servers/model/server/structure-wrapper.ts +++ b/src/servers/model/server/structure-wrapper.ts @@ -36,20 +36,22 @@ export interface StructureInfo { export interface StructureWrapper { info: StructureInfo, - isBinary: boolean, key: string, approximateSize: number, - structure: Structure, + models: ArrayLike<Model>, + modelMap: Map<number, Model>, + structureModelMap: Map<number, Structure>, + propertyProvider: ModelPropertiesProvider | undefined, cifFrame: CifFrame } -export async function getStructure(job: Job, propertyProvider: ModelPropertiesProvider | undefined, allowCache = true): Promise<StructureWrapper> { +export async function createStructureWrapperFromJob(job: Job, propertyProvider: ModelPropertiesProvider | undefined, 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, propertyProvider); + const ret = await readStructureWrapper(job.key, job.sourceId, job.entryId, propertyProvider); if (allowCache && Config.cacheParams.useCache) { StructureCache.add(ret); } @@ -86,7 +88,7 @@ async function parseCif(data: string|Uint8Array) { return parsed.result; } -export async function readStructure(key: string, sourceId: string | '_local_', entryId: string, propertyProvider: ModelPropertiesProvider | undefined) { +export async function readStructureWrapper(key: string, sourceId: string | '_local_', entryId: string, propertyProvider: ModelPropertiesProvider | undefined) { 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}'.`); @@ -108,6 +110,11 @@ export async function readStructure(key: string, sourceId: string | '_local_', e const models = await Model.create(Format.mmCIF(frame)).run(); perf.end('createModel'); + const modelMap = new Map<number, Model>(); + for (const m of models) { + modelMap.set(m.modelNum, m); + } + perf.start('attachProps'); if (propertyProvider) { const modelProps = propertyProvider(models[0]); @@ -117,28 +124,47 @@ export async function readStructure(key: string, sourceId: string | '_local_', e } perf.end('attachProps'); - const structure = Structure.ofModel(models[0]); - const ret: StructureWrapper = { info: { sourceType: StructureSourceType.File, readTime: perf.time('read'), parseTime: perf.time('parse'), createModelTime: perf.time('createModel'), - attachPropsTime: perf.time('attachProps'), + attachPropsTime: 0, // perf.time('attachProps'), sourceId, entryId }, isBinary: /\.bcif/.test(filename), key, approximateSize: typeof data === 'string' ? 2 * data.length : data.length, - structure, - cifFrame: frame + models, + modelMap, + structureModelMap: new Map(), + cifFrame: frame, + propertyProvider }; return ret; } +export async function resolveStructure(wrapper: StructureWrapper, modelNum?: number) { + if (typeof modelNum === 'undefined') modelNum = wrapper.models[0].modelNum; + if (wrapper.structureModelMap.has(modelNum)) return wrapper.structureModelMap.get(modelNum)!; + if (!wrapper.modelMap.has(modelNum)) { + return void 0; + } + + const model = wrapper.modelMap.get(modelNum)!; + const structure = Structure.ofModel(model); + if (wrapper.propertyProvider) { + const modelProps = wrapper.propertyProvider(model); + for (const p of modelProps) { + await tryAttach(wrapper.key, p); + } + } + return structure; +} + async function tryAttach(key: string, promise: Promise<any>) { try { await promise; -- GitLab