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

wip: multiple models export to CIF

parent 4ba3a5c8
No related branches found
No related tags found
No related merge requests found
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
import { CifWriter } from 'mol-io/writer/cif'; 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 { residueIdFields } from 'mol-model/structure/export/categories/atom_site';
import CifField = CifWriter.Field; import CifField = CifWriter.Field;
import { mmCIF_residueId_schema } from 'mol-io/reader/cif/schema/mmcif-extras'; import { mmCIF_residueId_schema } from 'mol-io/reader/cif/schema/mmcif-extras';
...@@ -50,6 +50,7 @@ type ExportCtx = ResidueCustomProperty.ExportCtx<string[]> ...@@ -50,6 +50,7 @@ type ExportCtx = ResidueCustomProperty.ExportCtx<string[]>
const _structure_quality_report_issues_fields: CifField<number, ExportCtx>[] = [ const _structure_quality_report_issues_fields: CifField<number, ExportCtx>[] = [
CifField.index('id'), CifField.index('id'),
...residueIdFields<number, ExportCtx>((i, d) => d.elements[i]), ...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(',')) CifField.str<number, ExportCtx>('issues', (i, d) => d.property(i).join(','))
]; ];
...@@ -83,9 +84,10 @@ function createIssueMapFromJson(modelData: Model, data: any): IssueMap | undefin ...@@ -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 { function createIssueMapFromCif(modelData: Model, data: Table<typeof StructureQualityReport.Schema.pdbe_structure_quality_report_issues>): IssueMap | undefined {
const ret = new Map<ResidueIndex, string[]>(); 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++) { 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)); 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)); ret.set(idx, issues.value(i));
} }
...@@ -103,6 +105,7 @@ export namespace StructureQualityReport { ...@@ -103,6 +105,7 @@ export namespace StructureQualityReport {
pdbe_structure_quality_report_issues: { pdbe_structure_quality_report_issues: {
id: Column.Schema.int, id: Column.Schema.int,
...mmCIF_residueId_schema, ...mmCIF_residueId_schema,
pdbx_PDB_model_num: Column.Schema.int,
issues: Column.Schema.List(',', x => x) issues: Column.Schema.List(',', x => x)
} }
} }
......
...@@ -21,8 +21,9 @@ export interface CifExportContext { ...@@ -21,8 +21,9 @@ export interface CifExportContext {
} }
export namespace CifExportContext { export namespace CifExportContext {
export function create(structure: Structure, model: Model): CifExportContext { export function create(structures: Structure | Structure[]): CifExportContext[] {
return { structure, model, cache: Object.create(null) }; 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 = { ...@@ -99,20 +100,20 @@ export const mmCIF_Export_Filters = {
} }
/** Doesn't start a data block */ /** Doesn't start a data block */
export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structure: Structure, params?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext }) { export function encode_mmCIF_categories(encoder: CifWriter.Encoder, structures: Structure | Structure[], params?: { skipCategoryNames?: Set<string>, exportCtx?: CifExportContext[] }) {
const models = structure.models; 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.'; if (models.length !== 1) throw 'Can\'t export stucture composed from multiple models.';
const model = models[0];
const _params = params || { }; const _params = params || { };
const ctx: CifExportContext[] = params && params.exportCtx ? params.exportCtx : CifExportContext.create(structures);
const ctx: CifExportContext[] = [_params.exportCtx ? _params.exportCtx : CifExportContext.create(structure, model)];
for (const cat of Categories) { for (const cat of Categories) {
if (_params.skipCategoryNames && _params.skipCategoryNames.has(cat.name)) continue; if (_params.skipCategoryNames && _params.skipCategoryNames.has(cat.name)) continue;
encoder.writeCategory(cat, ctx); 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; if (!customProp.cifExport || customProp.cifExport.categories.length === 0) continue;
const prefix = customProp.cifExport.prefix; const prefix = customProp.cifExport.prefix;
......
...@@ -25,12 +25,12 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu ...@@ -25,12 +25,12 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu
//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 readStructureWrapper('entry', '_local_', filename, void 0); const input = await readStructureWrapper('entry', '_local_', filename, void 0);
const categories = await classifyCif(input.cifFrame);
const inputStructure = (await resolveStructure(input))!; const inputStructure = (await resolveStructure(input))!;
//ConsoleLogger.log(`${linearId}`, `Classifying CIF categories...`); //ConsoleLogger.log(`${linearId}`, `Classifying CIF categories...`);
const categories = await classifyCif(input.cifFrame);
//clearLine(); //clearLine();
const exportCtx = CifExportContext.create(inputStructure, inputStructure.models[0]); const exportCtx = CifExportContext.create(inputStructure);
if (outputCif) { if (outputCif) {
//ConsoleLogger.log(`${linearId}`, `Encoding CIF...`); //ConsoleLogger.log(`${linearId}`, `Encoding CIF...`);
...@@ -52,7 +52,7 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu ...@@ -52,7 +52,7 @@ export async function preprocessFile(filename: string, outputCif?: string, outpu
// ConsoleLogger.log(`${linearId}`, `Finished '${filename}' in ${Math.round(now() - started)}ms`); // 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 => { return Task.create('Encode', async ctx => {
const skipCategoryNames = new Set<string>(categories.map(c => c.name)); const skipCategoryNames = new Set<string>(categories.map(c => c.name));
encoder.startDataBlock(header); encoder.startDataBlock(header);
......
...@@ -16,7 +16,7 @@ import Version from '../version'; ...@@ -16,7 +16,7 @@ import Version from '../version';
import { Job } from './jobs'; import { Job } from './jobs';
import { createStructureWrapperFromJob, StructureWrapper, resolveStructure } 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 '../property-provider';
export interface Stats { export interface Stats {
structure: StructureWrapper, structure: StructureWrapper,
...@@ -54,7 +54,7 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> { ...@@ -54,7 +54,7 @@ export async function resolveJob(job: Job): Promise<CifWriter.Encoder<any>> {
ConsoleLogger.logId(job.id, 'Query', 'Query finished.'); ConsoleLogger.logId(job.id, 'Query', 'Query finished.');
perf.start('encode'); 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_result, [job]);
encoder.writeCategory(_model_server_params, [job]); encoder.writeCategory(_model_server_params, [job]);
...@@ -132,7 +132,7 @@ const _model_server_error_fields: CifField<number, string>[] = [ ...@@ -132,7 +132,7 @@ const _model_server_error_fields: CifField<number, string>[] = [
const _model_server_stats_fields: CifField<number, Stats>[] = [ const _model_server_stats_fields: CifField<number, Stats>[] = [
int32<Stats>('io_time_ms', ctx => ctx.structure.info.readTime | 0), int32<Stats>('io_time_ms', ctx => ctx.structure.info.readTime | 0),
int32<Stats>('parse_time_ms', ctx => ctx.structure.info.parseTime | 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>('create_model_time_ms', ctx => ctx.structure.info.createModelTime | 0),
int32<Stats>('query_time_ms', ctx => ctx.queryTimeMs | 0), int32<Stats>('query_time_ms', ctx => ctx.queryTimeMs | 0),
int32<Stats>('encode_time_ms', ctx => ctx.encodeTimeMs | 0) int32<Stats>('encode_time_ms', ctx => ctx.encodeTimeMs | 0)
......
...@@ -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 { ModelPropertiesProvider } from '../provider'; import { ModelPropertiesProvider } from '../property-provider';
require('util.promisify').shim(); require('util.promisify').shim();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment