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

wip: multiple model support

parent e6e97c48
No related branches found
No related tags found
No related merge requests found
......@@ -8,10 +8,10 @@
import { Model } from 'mol-model/structure';
import { PDBe_structureQualityReport } from './providers/pdbe';
export function attachModelProperties(model: Model): Promise<any>[] {
export function attachModelProperties(model: Model, cache: object): Promise<any>[] {
// return a list of promises that start attaching the props in parallel
// (if there are downloads etc.)
return [
PDBe_structureQualityReport(model)
PDBe_structureQualityReport(model, cache)
];
}
\ No newline at end of file
......@@ -7,12 +7,20 @@
import { Model } from 'mol-model/structure';
import { StructureQualityReport } from 'mol-model-props/pdbe/structure-quality-report';
import { fetchRetry } from '../../utils/fetch-retry';
import { UUID } from 'mol-util';
export function PDBe_structureQualityReport(model: Model) {
const cacheKey = UUID.create();
export function PDBe_structureQualityReport(model: Model, cache: any) {
return StructureQualityReport.attachFromCifOrApi(model, {
PDBe_apiSourceJson: async model => {
if (cache[cacheKey]) {
console.log('cache hit');
return cache[cacheKey];
}
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();
const json = await rawData.json();
cache[cacheKey] = json;
return json;
}
});
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
import { Model } from 'mol-model/structure';
import Config from './config';
export type ModelPropertiesProvider = (model: Model) => Promise<any>[]
export type ModelPropertiesProvider = (model: Model, cache: object) => Promise<any>[]
export function createModelPropertiesProviderFromConfig(): ModelPropertiesProvider {
if (!Config.customPropertyProviders || Config.customPropertyProviders.length === 0) return () => [];
......@@ -17,10 +17,10 @@ export function createModelPropertiesProviderFromConfig(): ModelPropertiesProvid
ps.push(require(p).attachModelProperties);
}
return model => {
return (model, cache) => {
const ret: Promise<any>[] = [];
for (const p of ps) {
for (const e of p(model)) ret.push(e);
for (const e of p(model, cache)) ret.push(e);
}
return ret;
}
......
......@@ -6,7 +6,7 @@
import { Column } from 'mol-data/db';
import { CifWriter } from 'mol-io/writer/cif';
import { StructureQuery, StructureSelection } from 'mol-model/structure';
import { StructureQuery, StructureSelection, Structure } from 'mol-model/structure';
import { encode_mmCIF_categories } from 'mol-model/structure/export/mmcif';
import { now, Progress } from 'mol-task';
import { ConsoleLogger } from 'mol-util/console-logger';
......@@ -14,7 +14,7 @@ import { PerformanceMonitor } from 'mol-util/performance-monitor';
import Config from '../config';
import Version from '../version';
import { Job } from './jobs';
import { createStructureWrapperFromJob, StructureWrapper, resolveStructure } from './structure-wrapper';
import { createStructureWrapperFromJob, StructureWrapper, resolveStructures } from './structure-wrapper';
import CifField = CifWriter.Field
import { createModelPropertiesProviderFromConfig } from '../property-provider';
......@@ -35,13 +35,23 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> {
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, sourceStructure)
: sourceStructure;
const query = job.queryDefinition.query(job.normalizedParams, structure);
const result = await StructureSelection.unionStructure(StructureQuery.run(query, structure, Config.maxQueryTimeInMs));
const sourceStructures = await resolveStructures(wrappedStructure);
if (!sourceStructures.length) throw new Error('Model not available');
let structures: Structure[] = sourceStructures;
if (job.queryDefinition.structureTransform) {
structures = [];
for (const s of sourceStructures) {
structures.push(await job.queryDefinition.structureTransform(job.normalizedParams, s));
}
}
const queries = structures.map(s => job.queryDefinition.query(job.normalizedParams, s));
const result: Structure[] = [];
for (let i = 0; i < structures.length; i++) {
result.push(await StructureSelection.unionStructure(StructureQuery.run(queries[i], structures[i], Config.maxQueryTimeInMs)));
}
perf.end('query');
const encoder = CifWriter.createEncoder({
......@@ -54,7 +64,7 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> {
ConsoleLogger.logId(job.id, 'Query', 'Query finished.');
perf.start('encode');
encoder.startDataBlock(structure.models[0].label.toUpperCase());
encoder.startDataBlock(sourceStructures[0].models[0].label.toUpperCase());
encoder.writeCategory(_model_server_result, [job]);
encoder.writeCategory(_model_server_params, [job]);
......
......@@ -43,7 +43,8 @@ export interface StructureWrapper {
modelMap: Map<number, Model>,
structureModelMap: Map<number, Structure>,
propertyProvider: ModelPropertiesProvider | undefined,
cifFrame: CifFrame
cifFrame: CifFrame,
cache: object
}
export async function createStructureWrapperFromJob(job: Job, propertyProvider: ModelPropertiesProvider | undefined, allowCache = true): Promise<StructureWrapper> {
......@@ -115,15 +116,6 @@ export async function readStructureWrapper(key: string, sourceId: string | '_loc
modelMap.set(m.modelNum, m);
}
perf.start('attachProps');
if (propertyProvider) {
const modelProps = propertyProvider(models[0]);
for (const p of modelProps) {
await tryAttach(key, p);
}
}
perf.end('attachProps');
const ret: StructureWrapper = {
info: {
sourceType: StructureSourceType.File,
......@@ -141,7 +133,8 @@ export async function readStructureWrapper(key: string, sourceId: string | '_loc
modelMap,
structureModelMap: new Map(),
cifFrame: frame,
propertyProvider
propertyProvider,
cache: Object.create(null)
};
return ret;
......@@ -157,7 +150,7 @@ export async function resolveStructure(wrapper: StructureWrapper, modelNum?: num
const model = wrapper.modelMap.get(modelNum)!;
const structure = Structure.ofModel(model);
if (wrapper.propertyProvider) {
const modelProps = wrapper.propertyProvider(model);
const modelProps = wrapper.propertyProvider(model, wrapper.cache);
for (const p of modelProps) {
await tryAttach(wrapper.key, p);
}
......@@ -165,6 +158,15 @@ export async function resolveStructure(wrapper: StructureWrapper, modelNum?: num
return structure;
}
export async function resolveStructures(wrapper: StructureWrapper, modelNums?: number[]) {
const ret: Structure[] = [];
for (const n of modelNums || (wrapper.models as Model[]).map(m => m.modelNum)) {
const s = await resolveStructure(wrapper, n);
if (s) ret.push(s);
}
return ret;
}
async function tryAttach(key: string, promise: Promise<any>) {
try {
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