diff --git a/src/mol-model-props/pdbe/struct-ref-domain.ts b/src/mol-model-props/pdbe/struct-ref-domain.ts new file mode 100644 index 0000000000000000000000000000000000000000..3872d5a4d470fe0056024f961385846925f79bfe --- /dev/null +++ b/src/mol-model-props/pdbe/struct-ref-domain.ts @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Column, Table } from 'mol-data/db'; +import { toTable } from 'mol-io/reader/cif/schema'; +import { CifWriter } from 'mol-io/writer/cif'; +import { Model, ModelPropertyDescriptor } from 'mol-model/structure'; +import { PropertyWrapper } from '../common/wrapper'; + +export namespace PDBeStructRefDomain { + export type Property = PropertyWrapper<Table<Schema['pdbe_struct_ref_domain']> | undefined> + + export function get(model: Model): Property | undefined { + return model._staticPropertyData.__PDBeStructRefSeq__; + } + function set(model: Model, prop: Property) { + (model._staticPropertyData.__PDBeStructRefSeq__ as Property) = prop; + } + + export const Schema = { + pdbe_struct_ref_domain: { + id: Column.Schema.int, + db_name: Column.Schema.str, + db_code: Column.Schema.str, + + identifier: Column.Schema.str, + name: Column.Schema.str, + + label_entity_id: Column.Schema.str, + label_asym_id: Column.Schema.str, + beg_label_seq_id: Column.Schema.int, + beg_pdbx_PDB_ins_code: Column.Schema.str, + end_label_seq_id: Column.Schema.int, + end_pdbx_PDB_ins_code: Column.Schema.str + } + }; + export type Schema = typeof Schema + + export const Descriptor = ModelPropertyDescriptor({ + isStatic: true, + name: 'pdbe_struct_ref_domain', + cifExport: { + prefix: 'pdbe', + context(ctx): Property { return get(ctx.firstModel)!; }, + categories: [ + PropertyWrapper.defaultInfoCategory<Property>('pdbe_struct_ref_domain_info', ctx => ctx.info), + { + name: 'pdbe_struct_ref_domain', + instance(ctx: Property) { + if (!ctx || !ctx.data) return CifWriter.Category.Empty; + return CifWriter.Category.ofTable(ctx.data); + } + }] + } + }); + + function fromCifData(model: Model): Property['data'] { + if (model.sourceData.kind !== 'mmCIF') return void 0; + const cat = model.sourceData.frame.categories.pdbe_struct_ref_domain; + if (!cat) return void 0; + return toTable(Schema.pdbe_struct_ref_domain, cat); + } + + export async function attachFromCifOrApi(model: Model, params: { + // optional JSON source + PDBe_apiSourceJson?: (model: Model) => Promise<any> + }) { + if (model.customProperties.has(Descriptor)) return true; + + + let table: Property['data']; + let info = PropertyWrapper.tryGetInfoFromCif('pdbe_struct_ref_domain_info', model); + if (info) { + table = fromCifData(model); + } else if (params.PDBe_apiSourceJson) { + const data = await params.PDBe_apiSourceJson(model); + if (!data) return false; + info = PropertyWrapper.createInfo(); + table = fromPDBeJson(model, data); + } else { + return false; + } + + model.customProperties.add(Descriptor); + set(model, { info, data: table }); + return true; + } +} + +function fromPDBeJson(modelData: Model, data: any): PDBeStructRefDomain.Property['data'] { + const rows: Table.Row<PDBeStructRefDomain.Schema['pdbe_struct_ref_domain']>[] = []; + + let id = 1; + for (const db_name of Object.keys(data)) { + const db = data[db_name]; + for (const db_code of Object.keys(db)) { + const domain = db[db_code]; + for (const map of domain.mappings) { + rows.push({ + id: id++, + db_name, + db_code, + identifier: domain.identifier, + name: domain.name, + label_entity_id: '' + map.entity_id, + label_asym_id: map.struct_asym_id, + beg_label_seq_id: map.start.residue_number, + beg_pdbx_PDB_ins_code: map.start.author_insertion_code, + end_label_seq_id: map.end.residue_number, + end_pdbx_PDB_ins_code: map.end.author_insertion_code, + }) + } + } + } + + return Table.ofRows(PDBeStructRefDomain.Schema.pdbe_struct_ref_domain, rows) as PDBeStructRefDomain.Property['data']; +} \ No newline at end of file diff --git a/src/servers/model/properties/pdbe.ts b/src/servers/model/properties/pdbe.ts index ca26bad669735f7fc2e9fea5ec5045093b56342c..7f678a19b7656c56395bf110236beb4f6b2a5973 100644 --- a/src/servers/model/properties/pdbe.ts +++ b/src/servers/model/properties/pdbe.ts @@ -6,13 +6,14 @@ */ import { Model } from 'mol-model/structure'; -import { PDBe_structureQualityReport, PDBe_preferredAssembly } from './providers/pdbe'; +import { PDBe_structureQualityReport, PDBe_preferredAssembly, PDBe_structRefDomain } from './providers/pdbe'; 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, cache), - PDBe_preferredAssembly(model, cache) + PDBe_preferredAssembly(model, cache), + PDBe_structRefDomain(model, cache) ]; } \ No newline at end of file diff --git a/src/servers/model/properties/providers/pdbe.ts b/src/servers/model/properties/providers/pdbe.ts index d0d60dc0bc3963ad9e90995e38fd11569a6388fc..31a04a731644b81f11e23de5ca463e0f5c78529a 100644 --- a/src/servers/model/properties/providers/pdbe.ts +++ b/src/servers/model/properties/providers/pdbe.ts @@ -10,6 +10,7 @@ import { StructureQualityReport } from 'mol-model-props/pdbe/structure-quality-r import { fetchRetry } from '../../utils/fetch-retry'; import { UUID } from 'mol-util'; import { PDBePreferredAssembly } from 'mol-model-props/pdbe/preferred-assembly'; +import { PDBeStructRefDomain } from 'mol-model-props/pdbe/struct-ref-domain'; const USE_FILE_SOURCE = false; @@ -29,10 +30,22 @@ export function PDBe_preferredAssembly(model: Model, cache: any) { }); } +export function PDBe_structRefDomain(model: Model, cache: any) { + return PDBeStructRefDomain.attachFromCifOrApi(model, { + PDBe_apiSourceJson: USE_FILE_SOURCE + ? void 0 + : struct_ref_domain.getDataFromApiProvider(cache) + }); +} + namespace preferred_assembly { export const getDataFromApiProvider = apiQueryProvider('https://www.ebi.ac.uk/pdbe/api/pdb/entry/summary'); } +namespace struct_ref_domain { + export const getDataFromApiProvider = apiQueryProvider('https://www.ebi.ac.uk/pdbe/api/mappings/sequence_domains'); +} + namespace residuewise_outlier_summary { const json = new Map<string, any>(); diff --git a/src/servers/model/test.ts b/src/servers/model/test.ts index 58dc7414865a62af1f384d04bbdaa276a16f00ae..8d7f85b1e4dcbd354389f57bb6227c346e728608 100644 --- a/src/servers/model/test.ts +++ b/src/servers/model/test.ts @@ -49,7 +49,7 @@ async function run() { // queryName: 'full', // queryParams: { }, // }); - const testFile = '1grm_updated.cif' + const testFile = '1cbs_updated.cif' const request = createJob({ entryId: path.join(examplesPath, testFile), queryName: 'full',