From 8d9604edf298fa55bc11503824fccd050e958f59 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Sun, 5 Nov 2017 16:12:09 +0100 Subject: [PATCH] domain annotation server (prototype) --- package-lock.json | Bin 156627 -> 170121 bytes package.json | 14 ++- src/apps/domain-annotation-server/mapping.ts | 102 +++++++++++++++++++ src/apps/domain-annotation-server/schemas.ts | 89 ++++++++++++++++ src/apps/domain-annotation-server/server.ts | 48 +++++++++ src/apps/domain-annotation-server/test.ts | 14 +++ src/apps/domain-annotation-server/utils.ts | 43 ++++++++ src/mol-io/writer/cif/encoder.ts | 2 +- 8 files changed, 308 insertions(+), 4 deletions(-) create mode 100644 src/apps/domain-annotation-server/mapping.ts create mode 100644 src/apps/domain-annotation-server/schemas.ts create mode 100644 src/apps/domain-annotation-server/server.ts create mode 100644 src/apps/domain-annotation-server/test.ts create mode 100644 src/apps/domain-annotation-server/utils.ts diff --git a/package-lock.json b/package-lock.json index 1ce79bb2dc8d4d8557caa3e2f73f46de4c4992d2..445a602d57c899a8e98f013ba74f05382363076a 100644 GIT binary patch delta 7135 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 SaBxPJkzWAFRmxUO8#Dp#u@M;n delta 749 zcmeC&$aVQRr%*MQf`U?BVs5IEm4Z@keokioMp0+R&9ZE~jGIk4*cd0j<36}~KQFJy z=E+K02Aki8>IiN=k^W3<@{=tJoA=gVXWT5-?8Y^n?;Ru8WP?cxn~QsuL^gk0bcB7g z@>&bF%`#i$**8DmEziEW@c4HA%~x-1X5IYh{x$XOl3a{`87DKdD{NQhVJu?-vz7@k zPGj2sU6@f0Z2Wd5EyjyU+qd*G-eK7;F@>?6X?o{$#%0r09GMiR+st6xGucO4d%M6) z#%k8dQ(g;CUckdUea1Y-hugasGS>5LXW7WOOJMqqMn<0Le9sv<CckCkneM>BWHvqF zIiu9}XNMS{GfmIwW8#}^`<QQfK^>#X^oAphtlQrlV@%-Ro^+j2i+MWhJ4VIrvu-iE zvu;;-%$TG#IW$Ii`U7PqzU>ounV8tO&y`@>&$vBBnyHL`y4Wj5{>f>KV$<^-nM}67 z)@HKOVKkZUxRg<Ix_<<d*7P7oCf(^~tV}A?56olanZBlzNoTtFFGdkYlj(~08C51f z$Y%*l3^y+h^A0FYtMn-J&#kQVsY=)P(zY-&Fe@|7OD%IsPt3{m%n38k3oQuqEq2Mv zcXAKYPfiN<@ym*GOt&mFa866n*G^3=_73w7v?%j0wMfe|44l5vk<oGb`iV@e)3e!_ zRHr)xFmX>8jbaj-++!fbXgGZ#Ba_AStSBb&>4(agRHZHba*|D|vXe6-JhGE=LR_oL z&6AunJyOCe1E(j}F*!{C7{w$udG}ZTX(0M|F5mR_4~!z)EuxuTFikg(XZpx!HrY_p za5`Ty6Z`bo1SVldv&j#+ltT53ic>2qT)kbxe4X+wjLa=_3JdbR(p}7)^)vOIJu|f} zL%dwd!gG_fBl6913w^!Ivm7lv^Nl@yJ#vyG0;{qtEz?qi%&Lm~EOL#@3k%C~_46X9 sGrnUKpI*?)s4zW1h>3f<RwB~{mhEfOn37qxU&v<4X4?Kdk7<!60HA>g`~Uy| diff --git a/package.json b/package.json index d6ddc61c4..3185d9554 100644 --- a/package.json +++ b/package.json @@ -24,15 +24,20 @@ "transform": { "\\.ts$": "<rootDir>/node_modules/ts-jest/preprocessor.js" }, - "moduleDirectories": ["node_modules", "build/node_modules"], + "moduleDirectories": [ + "node_modules", + "build/node_modules" + ], "testRegex": "\\.spec\\.ts$" }, "author": "", "license": "MIT", "devDependencies": { "@types/benchmark": "^1.0.30", + "@types/express": "^4.0.39", "@types/jest": "^21.1.5", "@types/node": "^8.0.47", + "@types/node-fetch": "^1.6.7", "benchmark": "^2.1.4", "download-cli": "^1.0.5", "jest": "^21.2.1", @@ -45,8 +50,11 @@ "ts-jest": "^21.1.4", "tslint": "^5.8.0", "typescript": "^2.6.1", - "uglify-js": "^3.1.6", + "uglify-js": "^3.1.7", "util.promisify": "^1.0.0" }, - "dependencies": {} + "dependencies": { + "express": "^4.16.2", + "node-fetch": "^1.7.3" + } } diff --git a/src/apps/domain-annotation-server/mapping.ts b/src/apps/domain-annotation-server/mapping.ts new file mode 100644 index 000000000..4489cb959 --- /dev/null +++ b/src/apps/domain-annotation-server/mapping.ts @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Table } from 'mol-base/collections/database' +import { CIFEncoder, create as createEncoder } from 'mol-io/writer/cif' +import * as S from './schemas' +import { getCategoryInstanceProvider } from './utils' + +export default function create(allData: any) { + const mols = Object.keys(allData); + if (!mols.length) return '#'; + + const data = allData[mols[0]]; + + const enc = createEncoder(); + enc.startDataBlock(mols[0]); + + for (const cat of Object.keys(S.categories)) { + writeDomain(enc, getDomain(cat, (S.categories as any)[cat], data)); + } + return enc.getData(); +} + +interface DomainAnnotation { + name: string, + domains: Table<any>, + mappings: Table<S.mapping> +} +type MappingRow = Table.Row<S.mapping>; + +function writeDomain(enc: CIFEncoder<any>, domain: DomainAnnotation | undefined) { + if (!domain) return; + enc.writeCategory(getCategoryInstanceProvider(`pdbx_${domain.name}_domain_annotation`, domain.domains)); + enc.writeCategory(getCategoryInstanceProvider(`pdbx_${domain.name}_domain_mapping`, domain.mappings)); +} + +function getMappings(startId: number, group_id: number, mappings: any): MappingRow[] { + const rows: MappingRow[] = []; + + const n = (v: any) => v === null ? void 0 : v; + + for (const entry of mappings) { + if (entry.start && entry.end) { + rows.push({ + id: startId++, + group_id, + label_entity_id: '' + entry.entity_id, + label_asym_id: entry.struct_asym_id, + auth_asym_id: entry.chain_id, + beg_label_seq_id: n(entry.start.residue_number), + beg_auth_seq_id: n(entry.start.author_residue_number), + pdbx_beg_PDB_ins_code: entry.start.author_insertion_code, + end_label_seq_id: n(entry.end.residue_number), + end_auth_seq_id: n(entry.end.author_residue_number), + pdbx_end_PDB_ins_code: entry.end.author_insertion_code + }); + } else { + rows.push({ + id: startId++, + group_id, + label_entity_id: '' + entry.entity_id, + label_asym_id: entry.struct_asym_id, + auth_asym_id: entry.chain_id + } as any); + } + } + return rows; +} + +function getDomainInfo(id: string, mapping_group_id: number, data: any, schema: any) { + const props = Object.create(null); + for (const k of Object.keys(schema)) props[k] = data[k]; + return { id, mapping_group_id, identifier: data.identifier, ...props }; +} + +function getDomain(name: string, schema: any, allData: any) { + if (!allData[name]) return void 0; + + const data = allData[name]; + + const domains: any[] = []; + const mappings: MappingRow[] = []; + + let mappingSerialId = 1, mapping_group_id = 1; + + for (const id of Object.keys(data)) { + const domain = data[id]; + domains.push(getDomainInfo(id, mapping_group_id, domain, schema)); + mappings.push(...getMappings(mappingSerialId, mapping_group_id, domain.mappings)); + mappingSerialId = mappings.length + 1; + mapping_group_id++; + } + + return domains.length > 0 ? { + name, + domains: Table.ofRows({ ...S.Base, ...schema }, domains), + mappings: Table.ofRows(S.mapping, mappings) + } : void 0; +} \ No newline at end of file diff --git a/src/apps/domain-annotation-server/schemas.ts b/src/apps/domain-annotation-server/schemas.ts new file mode 100644 index 000000000..370bf1786 --- /dev/null +++ b/src/apps/domain-annotation-server/schemas.ts @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Column } from 'mol-base/collections/database' + +import Type = Column.Type + +export const Base = { + id: Type.str, + identifier: Type.str, + mapping_group_id: Type.int +} +export type Base = typeof Base + +export const mapping = { + id: Type.int, + group_id: Type.int, + + label_entity_id: Type.str, + label_asym_id: Type.str, + auth_asym_id: Type.str, + + beg_label_seq_id: Type.int, + beg_auth_seq_id: Type.int, + pdbx_beg_PDB_ins_code: Type.str, + + end_label_seq_id: Type.int, + end_auth_seq_id: Type.int, + pdbx_end_PDB_ins_code: Type.str +} +export type mapping = typeof mapping + +export const Pfam = { + description: Type.str +} +export type Pfam = typeof Pfam + +export const InterPro = { + name: Type.str +} +export type InterPro = typeof InterPro + +export const CATH = { + name: Type.str, + homology: Type.str, + architecture: Type.str, + identifier: Type.str, + class: Type.str, + topology: Type.str, +} +export type CATH = typeof CATH + +export const EC = { + accepted_name: Type.str, + reaction: Type.str, + systematic_name: Type.str +} +export type EC = typeof EC + +export const UniProt = { + name: Type.str +} +export type UniProt = typeof UniProt + +export const SCOP = { + sccs: Type.str, + description: Type.str +} +export type SCOP = typeof SCOP + +export const GO = { + category: Type.str, + definition: Type.str, + name: Type.str +} +export type GO = typeof GO + +export const categories = { + Pfam, + InterPro, + CATH, + EC, + UniProt, + SCOP, + GO +} \ No newline at end of file diff --git a/src/apps/domain-annotation-server/server.ts b/src/apps/domain-annotation-server/server.ts new file mode 100644 index 000000000..1d4f192ca --- /dev/null +++ b/src/apps/domain-annotation-server/server.ts @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import * as express from 'express' +import fetch from 'node-fetch' +import createMapping from './mapping' + +async function getMappings(id: string) { + const data = await fetch(`https://www.ebi.ac.uk/pdbe/api/mappings/${id}`); + const json = await data.json(); + return createMapping(json); +}; + + +let PORT = process.env.port || 1338; + +const app = express(); + +const PREFIX = '/' + +app.get(`${PREFIX}/:id`, async (req, res) => { + try { + console.log('Requesting ' + req.params.id); + const mapping = await getMappings(req.params.id); + res.writeHead(200, { + 'Content-Type': 'text/plain; charset=utf-8', + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'X-Requested-With' + }); + res.end(mapping); + } catch { + console.log('Failed ' + req.params.id); + res.writeHead(404, { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'X-Requested-With' }); + res.end(); + } +}); + +app.get(`${PREFIX}`, (req, res) => { + res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); + res.end('Usage: /pdb_id, e.g. /1tqn'); +}) + +app.listen(PORT); + +console.log('Running on port ' + PORT); \ No newline at end of file diff --git a/src/apps/domain-annotation-server/test.ts b/src/apps/domain-annotation-server/test.ts new file mode 100644 index 000000000..66911dec6 --- /dev/null +++ b/src/apps/domain-annotation-server/test.ts @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import fetch from 'node-fetch' +import createMapping from './mapping' + +(async function () { + const data = await fetch('https://www.ebi.ac.uk/pdbe/api/mappings/1tqn?pretty=true'); + const json = await data.json(); + console.log(createMapping(json)); +}()); \ No newline at end of file diff --git a/src/apps/domain-annotation-server/utils.ts b/src/apps/domain-annotation-server/utils.ts new file mode 100644 index 000000000..cb5c6badd --- /dev/null +++ b/src/apps/domain-annotation-server/utils.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Table } from 'mol-base/collections/database' +import Iterator from 'mol-base/collections/iterator' +import * as Encoder from 'mol-io/writer/cif' + +function columnValue(k: string) { + return (i: number, d: any) => d[k].value(i); +} + +function columnValueKind(k: string) { + return (i: number, d: any) => d[k].valueKind(i); +} + +function ofSchema(schema: Table.Schema) { + const fields: Encoder.FieldDefinition[] = []; + for (const k of Object.keys(schema)) { + const t = schema[k]; + // TODO: matrix/vector/support + const type = t.kind === 'str' ? Encoder.FieldType.Str : t.kind === 'int' ? Encoder.FieldType.Int : Encoder.FieldType.Float; + fields.push({ name: k, type, value: columnValue(k), valueKind: columnValueKind(k) }) + } + return fields; +} + +function ofTable<S extends Table.Schema>(name: string, table: Table<S>): Encoder.CategoryDefinition<number> { + return { name, fields: ofSchema(table._schema) } +} + +export function getCategoryInstanceProvider(name: string, table: Table<any>): Encoder.CategoryProvider { + return () => { + return { + data: table, + definition: ofTable(name, table), + keys: () => Iterator.Range(0, table._rowCount - 1), + rowCount: table._rowCount + }; + } +} diff --git a/src/mol-io/writer/cif/encoder.ts b/src/mol-io/writer/cif/encoder.ts index 64a18622f..f32bec34b 100644 --- a/src/mol-io/writer/cif/encoder.ts +++ b/src/mol-io/writer/cif/encoder.ts @@ -57,7 +57,7 @@ export interface CategoryProvider { (ctx: any): CategoryInstance } -export interface CIFEncoder<T, Context> extends Encoder<T> { +export interface CIFEncoder<T = string | Uint8Array, Context = any> extends Encoder<T> { startDataBlock(header: string): void, writeCategory(category: CategoryProvider, contexts?: Context[]): void, getData(): T -- GitLab