UNPKG

molstar

Version:

A comprehensive macromolecular library.

96 lines (95 loc) 4.26 kB
/** * Copyright (c) 2024 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org> */ import { MembraneServerConfig } from './config'; import { swaggerUiAssetsHandler, swaggerUiIndexHandler } from '../common/swagger-ui'; import { getSchema, shortcutIconLink } from './web-schema'; import { MembraneOrientationProvider } from '../../extensions/anvil/prop'; import { SyncRuntimeContext } from '../../mol-task/execution/synchronous'; import { AssetManager } from '../../mol-util/assets'; import { CIF } from '../../mol-io/reader/cif'; import { Structure, StructureSymmetry } from '../../mol-model/structure'; import { trajectoryFromMmCIF } from '../../mol-model-formats/structure/mmcif'; import { ANVILParams } from '../../extensions/anvil/algorithm'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ConsoleLogger } from '../../mol-util/console-logger'; const assetManager = new AssetManager(); export function initWebApi(app) { function makePath(p) { return MembraneServerConfig.apiPrefix + '/' + p; } app.get(makePath('predict/:id/'), async (req, res) => predictMembraneOrientation(req, res)); app.get(makePath('openapi.json'), (_, res) => { res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'X-Requested-With' }); res.end(JSON.stringify(getSchema())); }); app.use(makePath(''), swaggerUiAssetsHandler()); app.get(makePath(''), swaggerUiIndexHandler({ openapiJsonUrl: makePath('openapi.json'), apiPrefix: MembraneServerConfig.apiPrefix, title: 'MembraneServer API', shortcutIconLink })); } async function predictMembraneOrientation(req, res) { var _a; try { const ctx = { runtime: SyncRuntimeContext, assetManager }; const entryId = req.params.id; const assemblyId = (_a = req.query.assemblyId) !== null && _a !== void 0 ? _a : '1'; const p = parseParams(req); ConsoleLogger.log('predictMembraneOrientation', `${entryId}-${assemblyId} with params: ${JSON.stringify(p)}`); const cif = await downloadFromPdb(entryId); const models = await getModels(cif); const structure = await getStructure(models.representative, assemblyId); await MembraneOrientationProvider.attach(ctx, structure, p); const data = MembraneOrientationProvider.get(structure).value; res.status(200).json(data); } catch (e) { const error = 'Failed to compute membrane orientation'; ConsoleLogger.error(error, e); res.status(500).json({ error }); } } const defaults = PD.getDefaultValues(ANVILParams); function parseParams(req) { const { numberOfSpherePoints = defaults.numberOfSpherePoints, stepSize = defaults.stepSize, minThickness = defaults.minThickness, maxThickness = defaults.maxThickness, asaCutoff = defaults.asaCutoff, adjust = defaults.adjust, tmdetDefinition = defaults.tmdetDefinition, } = req.query; return { numberOfSpherePoints: Number(numberOfSpherePoints), stepSize: Number(stepSize), minThickness: Number(minThickness), maxThickness: Number(maxThickness), asaCutoff: Number(asaCutoff), adjust: Number(adjust), tmdetDefinition: tmdetDefinition === 'true', }; } async function parseCif(data) { const comp = CIF.parse(data); const parsed = await comp.run(); if (parsed.isError) throw parsed; return parsed.result; } async function downloadCif(url, isBinary) { const data = await fetch(url); return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text()); } async function downloadFromPdb(pdb) { const parsed = await downloadCif(MembraneServerConfig.bcifSource(pdb), true); return parsed.blocks[0]; } async function getModels(frame) { return await trajectoryFromMmCIF(frame).run(); } async function getStructure(model, assemblyId) { const modelStructure = Structure.ofModel(model); return await StructureSymmetry.buildAssembly(modelStructure, assemblyId).run(); }