diff --git a/src/mol-model-props/pdbe/structure-quality-report.ts b/src/mol-model-props/pdbe/structure-quality-report.ts index 2d6b11e3f7726ef9302f5c081db4e57820154f4b..8eed13c6f251255351d7570612a7233f88ccad6f 100644 --- a/src/mol-model-props/pdbe/structure-quality-report.ts +++ b/src/mol-model-props/pdbe/structure-quality-report.ts @@ -5,7 +5,7 @@ */ import { CifWriter } from 'mol-io/writer/cif'; -import { Model, ModelPropertyDescriptor, ResidueIndex, Unit, ResidueCustomProperty } from 'mol-model/structure'; +import { Model, ModelPropertyDescriptor, ResidueIndex, Unit, ResidueCustomProperty, StructureProperties as P } from 'mol-model/structure'; import { residueIdFields } from 'mol-model/structure/export/categories/atom_site'; import CifField = CifWriter.Field; import { mmCIF_residueId_schema } from 'mol-io/reader/cif/schema/mmcif-extras'; @@ -50,6 +50,7 @@ type ExportCtx = ResidueCustomProperty.ExportCtx<string[]> const _structure_quality_report_issues_fields: CifField<number, ExportCtx>[] = [ CifField.index('id'), ...residueIdFields<number, ExportCtx>((i, d) => d.elements[i]), + CifField.int<number, ExportCtx>('pdbx_PDB_model_num', (i, d) => P.unit.model_num(d.elements[i])), CifField.str<number, ExportCtx>('issues', (i, d) => d.property(i).join(',')) ]; @@ -83,9 +84,10 @@ function createIssueMapFromJson(modelData: Model, data: any): IssueMap | undefin function createIssueMapFromCif(modelData: Model, data: Table<typeof StructureQualityReport.Schema.pdbe_structure_quality_report_issues>): IssueMap | undefined { const ret = new Map<ResidueIndex, string[]>(); - const { label_entity_id, label_asym_id, auth_seq_id, pdbx_PDB_ins_code, issues, _rowCount } = data; + const { label_entity_id, label_asym_id, auth_seq_id, pdbx_PDB_ins_code, issues, pdbx_PDB_model_num, _rowCount } = data; for (let i = 0; i < _rowCount; i++) { + if (pdbx_PDB_model_num.value(i) !== modelData.modelNum) continue; const idx = modelData.atomicHierarchy.index.findResidue(label_entity_id.value(i), label_asym_id.value(i), auth_seq_id.value(i), pdbx_PDB_ins_code.value(i)); ret.set(idx, issues.value(i)); } @@ -103,6 +105,7 @@ export namespace StructureQualityReport { pdbe_structure_quality_report_issues: { id: Column.Schema.int, ...mmCIF_residueId_schema, + pdbx_PDB_model_num: Column.Schema.int, issues: Column.Schema.List(',', x => x) } } diff --git a/src/mol-model/structure/export/mmcif.ts b/src/mol-model/structure/export/mmcif.ts index 2bfa34c5609985e4f10e006109f0baffbeb80905..3f793d3d2a0634ba3a43e695d3a4b8ce51025408 100644 --- a/src/mol-model/structure/export/mmcif.ts +++ b/src/mol-model/structure/export/mmcif.ts @@ -21,8 +21,9 @@ export interface CifExportContext { } export namespace CifExportContext { - export function create(structure: Structure, model: Model): CifExportContext { - return { structure, model, cache: Object.create(null) }; + export function create(structures: Structure | Structure[]): CifExportContext[] { + if (Array.isArray(structures)) return structures.map(structure => ({ structure, model: structure.models[0], cache: Object.create(null) })); + return [{ structure: structures, model: structures.models[0], cache: Object.create(null) }]; } } @@ -99,20 +100,20 @@ export const mmCIF_Export_Filters = { } /** Doesn't start a data block */ -export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: Structure, params?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext }) { - const models = structure.models; +export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structures: Structure | Structure[], params?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext[] }) { + const first = Array.isArray(structures) ? structures[0] : (structures as Structure); + const models = first.models; if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.'; - const model = models[0]; const _params = params || { }; - - const ctx: CifExportContext[] = [_params.exportCtx ? _params.exportCtx : CifExportContext.create(structure, model)]; + const ctx: CifExportContext[] = params && params.exportCtx ? params.exportCtx : CifExportContext.create(structures); 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) { + + for (const customProp of models[0].customProperties.all) { if (!customProp.cifExport || customProp.cifExport.categories.length === 0) continue; const prefix = customProp.cifExport.prefix; diff --git a/src/servers/model/preprocess/preprocess.ts b/src/servers/model/preprocess/preprocess.ts index f54468091666e97985aedc7a1d56855bb305e496..5047d6635cde9ec48e175cdd614d76c20d1f6136 100644 --- a/src/servers/model/preprocess/preprocess.ts +++ b/src/servers/model/preprocess/preprocess.ts @@ -25,12 +25,12 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu //ConsoleLogger.log(`${linearId}`, `Reading '${filename}'...`); // TODO: support the custom prop provider list here. const input = await readStructureWrapper('entry', '_local_', filename, void 0); + const categories = await classifyCif(input.cifFrame); const inputStructure = (await resolveStructure(input))!; //ConsoleLogger.log(`${linearId}`, `Classifying CIF categories...`); - const categories = await classifyCif(input.cifFrame); //clearLine(); - const exportCtx = CifExportContext.create(inputStructure, inputStructure.models[0]); + const exportCtx = CifExportContext.create(inputStructure); if (outputCif) { //ConsoleLogger.log(`${linearId}`, `Encoding CIF...`); @@ -52,7 +52,7 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu // ConsoleLogger.log(`${linearId}`, `Finished '${filename}' in ${Math.round(now() - started)}ms`); } -function encode(structure: Structure, header: string, categories: CifWriter.Category[], encoder: CifWriter.Encoder, exportCtx: CifExportContext, writer: Writer) { +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); diff --git a/src/servers/model/provider.ts b/src/servers/model/property-provider.ts similarity index 100% rename from src/servers/model/provider.ts rename to src/servers/model/property-provider.ts diff --git a/src/servers/model/server/query.ts b/src/servers/model/server/query.ts index 50c04e0c9a19ffe485c26dc956a4222d7e449eaf..35159b5dc3f4754618aca8e7933b8fdc5a53d373 100644 --- a/src/servers/model/server/query.ts +++ b/src/servers/model/server/query.ts @@ -16,7 +16,7 @@ import Version from '../version'; import { Job } from './jobs'; import { createStructureWrapperFromJob, StructureWrapper, resolveStructure } from './structure-wrapper'; import CifField = CifWriter.Field -import { createModelPropertiesProviderFromConfig } from '../provider'; +import { createModelPropertiesProviderFromConfig } from '../property-provider'; export interface Stats { structure: StructureWrapper, @@ -54,7 +54,7 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> { ConsoleLogger.logId(job.id, 'Query', 'Query finished.'); perf.start('encode'); - encoder.startDataBlock(structure.units[0].model.label.toUpperCase()); + encoder.startDataBlock(structure.models[0].label.toUpperCase()); encoder.writeCategory(_model_server_result, [job]); encoder.writeCategory(_model_server_params, [job]); @@ -132,7 +132,7 @@ const _model_server_error_fields: CifField<number, string>[] = [ const _model_server_stats_fields: CifField<number, Stats>[] = [ int32<Stats>('io_time_ms', ctx => ctx.structure.info.readTime | 0), int32<Stats>('parse_time_ms', ctx => ctx.structure.info.parseTime | 0), - int32<Stats>('attach_props_time_ms', ctx => ctx.structure.info.attachPropsTime | 0), + // int32<Stats>('attach_props_time_ms', ctx => ctx.structure.info.attachPropsTime | 0), int32<Stats>('create_model_time_ms', ctx => ctx.structure.info.createModelTime | 0), int32<Stats>('query_time_ms', ctx => ctx.queryTimeMs | 0), int32<Stats>('encode_time_ms', ctx => ctx.encodeTimeMs | 0) diff --git a/src/servers/model/server/structure-wrapper.ts b/src/servers/model/server/structure-wrapper.ts index d7ffc7f2d2da722aeaff4a45a299b4a797be05c0..60275ddc5f2a514cefd9243f536c0e752bc811cf 100644 --- a/src/servers/model/server/structure-wrapper.ts +++ b/src/servers/model/server/structure-wrapper.ts @@ -14,7 +14,7 @@ import * as fs from 'fs' import * as zlib from 'zlib' import { Job } from './jobs'; import { ConsoleLogger } from 'mol-util/console-logger'; -import { ModelPropertiesProvider } from '../provider'; +import { ModelPropertiesProvider } from '../property-provider'; require('util.promisify').shim();