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

ModelServer: custom property providers defined by config file

parent 43a9d739
No related branches found
No related tags found
No related merge requests found
...@@ -47,6 +47,14 @@ const config = { ...@@ -47,6 +47,14 @@ const config = {
/** Maximum number of requests before "server busy" */ /** Maximum number of requests before "server busy" */
maxQueueLength: 30, maxQueueLength: 30,
/**
* Paths (relative to the root directory of the model server) to JavaScript files that specify custom properties
*/
customPropertyProviders: [
'./properties/pdbe',
'./properties/rcsb'
],
/** /**
* Maps a request identifier to a filename. * Maps a request identifier to a filename.
* *
......
...@@ -23,7 +23,8 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu ...@@ -23,7 +23,8 @@ 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}'...`);
const input = await readStructure('entry', '_local_', filename); // TODO: support the custom prop provider list here.
const input = await readStructure('entry', '_local_', filename, void 0);
//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();
......
...@@ -2,17 +2,16 @@ ...@@ -2,17 +2,16 @@
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import { Model } from 'mol-model/structure'; import { Model } from 'mol-model/structure';
import { StructureQualityReport } from 'mol-model-props/pdbe/structure-quality-report'; import { PDBe_structureQualityReport } from './providers/pdbe';
import { fetchRetry } from '../utils/fetch-retry';
export function PDBe_structureQualityReport(model: Model) { export function attachModelProperties(model: Model): Promise<any>[] {
return StructureQualityReport.attachFromCifOrApi(model, { // return a list of promises that start attaching the props in parallel
PDBe_apiSourceJson: async model => { // (if there are downloads etc.)
const rawData = await fetchRetry(`https://www.ebi.ac.uk/pdbe/api/validation/residuewise_outlier_summary/entry/${model.label.toLowerCase()}`, 1500, 5); return [
return await rawData.json(); PDBe_structureQualityReport(model)
} ];
});
} }
\ 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 { Model } from 'mol-model/structure';
import { StructureQualityReport } from 'mol-model-props/pdbe/structure-quality-report';
import { fetchRetry } from '../../utils/fetch-retry';
export function PDBe_structureQualityReport(model: Model) {
return StructureQualityReport.attachFromCifOrApi(model, {
PDBe_apiSourceJson: async model => {
const rawData = await fetchRetry(`https://www.ebi.ac.uk/pdbe/api/validation/residuewise_outlier_summary/entry/${model.label.toLowerCase()}`, 1500, 5);
return await rawData.json();
}
});
}
\ No newline at end of file
/** /**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import { Model } from 'mol-model/structure'; import { Model } from 'mol-model/structure';
//import { PDBe_structureQualityReport } from './properties/pdbe'; import { AssemblySymmetry } from 'mol-model-props/rcsb/symmetry';
//import { RCSB_assemblySymmetry } from './properties/rcsb';
export function attachModelProperties(model: Model): Promise<any>[] { export function RCSB_assemblySymmetry(model: Model) {
// return a list of promises that start attaching the props in parallel return AssemblySymmetry.attachFromCifOrAPI(model)
// (if there are downloads etc.)
return [
//PDBe_structureQualityReport(model),
//RCSB_assemblySymmetry(model)
];
} }
\ No newline at end of file
/** /**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import { Model } from 'mol-model/structure'; import { Model } from 'mol-model/structure';
import { AssemblySymmetry } from 'mol-model-props/rcsb/symmetry'; import { RCSB_assemblySymmetry } from './providers/rcsb';
export function RCSB_assemblySymmetry(model: Model) { export function attachModelProperties(model: Model): Promise<any>[] {
return AssemblySymmetry.attachFromCifOrAPI(model) // return a list of promises that start attaching the props in parallel
// (if there are downloads etc.)
return [
RCSB_assemblySymmetry(model)
];
} }
\ 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 { Model } from 'mol-model/structure';
import Config from './config';
export type ModelPropertiesProvider = (model: Model) => Promise<any>[]
export function createModelPropertiesProviderFromConfig(): ModelPropertiesProvider {
if (!Config.customPropertyProviders || Config.customPropertyProviders.length === 0) return () => [];
const ps: ModelPropertiesProvider[] = [];
for (const p of Config.customPropertyProviders) {
ps.push(require(p).attachModelProperties);
}
return model => {
const ret: Promise<any>[] = [];
for (const p of ps) {
for (const e of p(model)) ret.push(e);
}
return ret;
}
}
...@@ -16,6 +16,7 @@ import Version from '../version'; ...@@ -16,6 +16,7 @@ import Version from '../version';
import { Job } from './jobs'; import { Job } from './jobs';
import { getStructure, StructureWrapper } from './structure-wrapper'; import { getStructure, StructureWrapper } from './structure-wrapper';
import CifField = CifWriter.Field import CifField = CifWriter.Field
import { createModelPropertiesProviderFromConfig } from '../provider';
export interface Stats { export interface Stats {
structure: StructureWrapper, structure: StructureWrapper,
...@@ -25,10 +26,12 @@ export interface Stats { ...@@ -25,10 +26,12 @@ export interface Stats {
const perf = new PerformanceMonitor(); const perf = new PerformanceMonitor();
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); const wrappedStructure = await getStructure(job, propertyProvider);
try { try {
perf.start('query'); perf.start('query');
......
...@@ -14,7 +14,7 @@ import * as fs from 'fs' ...@@ -14,7 +14,7 @@ import * as fs from 'fs'
import * as zlib from 'zlib' import * as zlib from 'zlib'
import { Job } from './jobs'; import { Job } from './jobs';
import { ConsoleLogger } from 'mol-util/console-logger'; import { ConsoleLogger } from 'mol-util/console-logger';
import { attachModelProperties } from '../properties'; import { ModelPropertiesProvider } from '../provider';
require('util.promisify').shim(); require('util.promisify').shim();
...@@ -44,12 +44,12 @@ export interface StructureWrapper { ...@@ -44,12 +44,12 @@ export interface StructureWrapper {
cifFrame: CifFrame cifFrame: CifFrame
} }
export async function getStructure(job: Job, allowCache = true): Promise<StructureWrapper> { export async function getStructure(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); const ret = await readStructure(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 +86,7 @@ async function parseCif(data: string|Uint8Array) { ...@@ -86,7 +86,7 @@ async function parseCif(data: string|Uint8Array) {
return parsed.result; return parsed.result;
} }
export async function readStructure(key: string, sourceId: string | '_local_', entryId: string) { export async function readStructure(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}'.`);
...@@ -109,9 +109,11 @@ export async function readStructure(key: string, sourceId: string | '_local_', e ...@@ -109,9 +109,11 @@ export async function readStructure(key: string, sourceId: string | '_local_', e
perf.end('createModel'); perf.end('createModel');
perf.start('attachProps'); perf.start('attachProps');
const modelProps = attachModelProperties(models[0]); if (propertyProvider) {
for (const p of modelProps) { const modelProps = propertyProvider(models[0]);
await tryAttach(key, p); for (const p of modelProps) {
await tryAttach(key, p);
}
} }
perf.end('attachProps'); perf.end('attachProps');
......
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