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

wip ModelServer multiple model support

parent 717da8d1
No related branches found
No related tags found
No related merge requests found
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* @author David Sehnal <david.sehnal@gmail.com> * @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 { classifyCif } from './converter';
// import { ConsoleLogger } from 'mol-util/console-logger'; // import { ConsoleLogger } from 'mol-util/console-logger';
import { Structure } from 'mol-model/structure'; import { Structure } from 'mol-model/structure';
...@@ -24,18 +24,19 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu ...@@ -24,18 +24,19 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu
//const started = now(); //const started = now();
//ConsoleLogger.log(`${linearId}`, `Reading '${filename}'...`); //ConsoleLogger.log(`${linearId}`, `Reading '${filename}'...`);
// TODO: support the custom prop provider list here. // 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...`); //ConsoleLogger.log(`${linearId}`, `Classifying CIF categories...`);
const categories = await classifyCif(input.cifFrame); const categories = await classifyCif(input.cifFrame);
//clearLine(); //clearLine();
const exportCtx = CifExportContext.create(input.structure, input.structure.models[0]); const exportCtx = CifExportContext.create(inputStructure, inputStructure.models[0]);
if (outputCif) { if (outputCif) {
//ConsoleLogger.log(`${linearId}`, `Encoding CIF...`); //ConsoleLogger.log(`${linearId}`, `Encoding CIF...`);
const writer = wrapFileToWriter(outputCif); const writer = wrapFileToWriter(outputCif);
const encoder = CifWriter.createEncoder({ binary: false }); 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(); // clearLine();
writer.end(); writer.end();
} }
...@@ -44,7 +45,7 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu ...@@ -44,7 +45,7 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu
// ConsoleLogger.log(`${linearId}`, `Encoding BinaryCIF...`); // ConsoleLogger.log(`${linearId}`, `Encoding BinaryCIF...`);
const writer = wrapFileToWriter(outputBcif); const writer = wrapFileToWriter(outputBcif);
const encoder = CifWriter.createEncoder({ binary: true, binaryAutoClassifyEncoding: true }); 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(); //clearLine();
writer.end(); writer.end();
} }
......
...@@ -14,7 +14,7 @@ import { PerformanceMonitor } from 'mol-util/performance-monitor'; ...@@ -14,7 +14,7 @@ import { PerformanceMonitor } from 'mol-util/performance-monitor';
import Config from '../config'; import Config from '../config';
import Version from '../version'; import Version from '../version';
import { Job } from './jobs'; import { Job } from './jobs';
import { getStructure, StructureWrapper } from './structure-wrapper'; import { createStructureWrapperFromJob, StructureWrapper, resolveStructure } from './structure-wrapper';
import CifField = CifWriter.Field import CifField = CifWriter.Field
import { createModelPropertiesProviderFromConfig } from '../provider'; import { createModelPropertiesProviderFromConfig } from '../provider';
...@@ -31,13 +31,15 @@ const propertyProvider = createModelPropertiesProviderFromConfig(); ...@@ -31,13 +31,15 @@ const propertyProvider = createModelPropertiesProviderFromConfig();
export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> { export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> {
ConsoleLogger.logId(job.id, 'Query', 'Starting.'); ConsoleLogger.logId(job.id, 'Query', 'Starting.');
const wrappedStructure = await getStructure(job, propertyProvider); const wrappedStructure = await createStructureWrapperFromJob(job, propertyProvider);
try { try {
perf.start('query'); perf.start('query');
const sourceStructure = await resolveStructure(wrappedStructure);
if (!sourceStructure) throw new Error('Model not available');
const structure = job.queryDefinition.structureTransform const structure = job.queryDefinition.structureTransform
? await job.queryDefinition.structureTransform(job.normalizedParams, wrappedStructure.structure) ? await job.queryDefinition.structureTransform(job.normalizedParams, sourceStructure)
: wrappedStructure.structure; : sourceStructure;
const query = job.queryDefinition.query(job.normalizedParams, structure); const query = job.queryDefinition.query(job.normalizedParams, structure);
const result = await StructureSelection.unionStructure(StructureQuery.run(query, structure, Config.maxQueryTimeInMs)); const result = await StructureSelection.unionStructure(StructureQuery.run(query, structure, Config.maxQueryTimeInMs));
perf.end('query'); perf.end('query');
......
...@@ -36,20 +36,22 @@ export interface StructureInfo { ...@@ -36,20 +36,22 @@ export interface StructureInfo {
export interface StructureWrapper { export interface StructureWrapper {
info: StructureInfo, info: StructureInfo,
isBinary: boolean, isBinary: boolean,
key: string, key: string,
approximateSize: number, approximateSize: number,
structure: Structure, models: ArrayLike<Model>,
modelMap: Map<number, Model>,
structureModelMap: Map<number, Structure>,
propertyProvider: ModelPropertiesProvider | undefined,
cifFrame: CifFrame 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) { if (allowCache && Config.cacheParams.useCache) {
const ret = StructureCache.get(job.key); const ret = StructureCache.get(job.key);
if (ret) return ret; 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) { if (allowCache && Config.cacheParams.useCache) {
StructureCache.add(ret); StructureCache.add(ret);
} }
...@@ -86,7 +88,7 @@ async function parseCif(data: string|Uint8Array) { ...@@ -86,7 +88,7 @@ async function parseCif(data: string|Uint8Array) {
return parsed.result; 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); const filename = sourceId === '_local_' ? entryId : Config.mapFile(sourceId, entryId);
if (!filename) throw new Error(`Cound not map '${key}' to a valid filename.`); 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}'.`); 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 ...@@ -108,6 +110,11 @@ export async function readStructure(key: string, sourceId: string | '_local_', e
const models = await Model.create(Format.mmCIF(frame)).run(); const models = await Model.create(Format.mmCIF(frame)).run();
perf.end('createModel'); perf.end('createModel');
const modelMap = new Map<number, Model>();
for (const m of models) {
modelMap.set(m.modelNum, m);
}
perf.start('attachProps'); perf.start('attachProps');
if (propertyProvider) { if (propertyProvider) {
const modelProps = propertyProvider(models[0]); const modelProps = propertyProvider(models[0]);
...@@ -117,28 +124,47 @@ export async function readStructure(key: string, sourceId: string | '_local_', e ...@@ -117,28 +124,47 @@ export async function readStructure(key: string, sourceId: string | '_local_', e
} }
perf.end('attachProps'); perf.end('attachProps');
const structure = Structure.ofModel(models[0]);
const ret: StructureWrapper = { const ret: StructureWrapper = {
info: { info: {
sourceType: StructureSourceType.File, sourceType: StructureSourceType.File,
readTime: perf.time('read'), readTime: perf.time('read'),
parseTime: perf.time('parse'), parseTime: perf.time('parse'),
createModelTime: perf.time('createModel'), createModelTime: perf.time('createModel'),
attachPropsTime: perf.time('attachProps'), attachPropsTime: 0, // perf.time('attachProps'),
sourceId, sourceId,
entryId entryId
}, },
isBinary: /\.bcif/.test(filename), isBinary: /\.bcif/.test(filename),
key, key,
approximateSize: typeof data === 'string' ? 2 * data.length : data.length, approximateSize: typeof data === 'string' ? 2 * data.length : data.length,
structure, models,
cifFrame: frame modelMap,
structureModelMap: new Map(),
cifFrame: frame,
propertyProvider
}; };
return ret; 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>) { async function tryAttach(key: string, promise: Promise<any>) {
try { try {
await promise; await promise;
......
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