UNPKG

molstar

Version:

A comprehensive macromolecular library.

150 lines (149 loc) 6.33 kB
/** * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { TrajectoryFormatCategory } from '../../mol-plugin-state/formats/trajectory'; import { PluginStateObject as SO, PluginStateTransform } from '../../mol-plugin-state/objects'; import { PluginBehavior } from '../../mol-plugin/behavior'; import { DefaultQueryRuntimeTable } from '../../mol-script/runtime/query/base'; import { StateAction } from '../../mol-state'; import { Task } from '../../mol-task'; import { ParamDefinition } from '../../mol-util/param-definition'; import { getG3dDataBlock, getG3dHeader } from './data'; import { g3dHaplotypeQuery, G3dLabelProvider, trajectoryFromG3D, G3dSymbols, G3dInfoDataProperty } from './model'; import { StateTransforms } from '../../mol-plugin-state/transforms'; import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params'; import { stringToWords } from '../../mol-util/string'; import { objectForEach } from '../../mol-util/object'; export const G3dProvider = { label: 'G3D', description: 'G3D', category: TrajectoryFormatCategory, binaryExtensions: ['g3d'], parse: async (plugin, data) => { const trajectory = await plugin.state.data.build() .to(data) .apply(G3DHeaderFromFile, {}, { state: { isGhost: true } }) .apply(G3DTrajectory) .commit(); return { trajectory }; }, visuals: defaultStructure }; async function defaultStructure(plugin, data) { const builder = plugin.builders.structure; const model = await builder.createModel(data.trajectory); if (!model) return; const structure = await builder.createStructure(model); const info = G3dInfoDataProperty.get(model.data); if (!info) return; const components = plugin.build().to(structure); const repr = createStructureRepresentationParams(plugin, void 0, { type: 'cartoon', color: 'polymer-index', size: 'uniform', sizeParams: { value: 0.25 } }); for (const h of info.haplotypes) { components .apply(StateTransforms.Model.StructureSelectionFromExpression, { expression: g3dHaplotypeQuery(h), label: stringToWords(h) }) .apply(StateTransforms.Representation.StructureRepresentation3D, repr); } await components.commit(); } export class G3dHeaderObject extends SO.Create({ name: 'G3D Header', typeClass: 'Data' }) { } export const G3DHeaderFromFile = PluginStateTransform.BuiltIn({ name: 'g3d-header-from-file', display: { name: 'G3D Header', description: 'Parse G3D Header' }, from: SO.Data.Binary, to: G3dHeaderObject })({ apply({ a }, plugin) { return Task.create('Parse G3D', async () => { const header = await getG3dHeader(plugin, a.data); return new G3dHeaderObject({ header, urlOrData: a.data, cache: {} }, { label: header.name, description: header.genome }); }); } }); export const G3DHeaderFromUrl = PluginStateTransform.BuiltIn({ name: 'g3d-header-from-url', display: { name: 'G3D Header', description: 'Parse G3D Header' }, params: { url: ParamDefinition.Text('') }, from: SO.Root, to: G3dHeaderObject })({ apply({ params }, plugin) { return Task.create('Parse G3D', async () => { const header = await getG3dHeader(plugin, params.url); return new G3dHeaderObject({ header, urlOrData: params.url, cache: {} }, { label: header.name, description: header.genome }); }); } }); export const G3DTrajectory = PluginStateTransform.BuiltIn({ name: 'g3d-trajecotry', display: { name: 'G3D Trajectory', description: 'Create G3D Trajectory' }, params: a => { if (!a) return { resolution: ParamDefinition.Numeric(200000) }; const rs = a.data.header.resolutions; return { resolution: ParamDefinition.Select(rs[rs.length - 1], rs.map(r => [r, '' + r])) }; }, from: G3dHeaderObject, to: SO.Molecule.Trajectory })({ apply({ a, params }, plugin) { return Task.create('G3D Trajectory', async (ctx) => { if (a.data.cache[params.resolution]) { return new SO.Molecule.Trajectory(a.data.cache[params.resolution], { label: a.label, description: a.description }); } const data = await getG3dDataBlock(plugin, a.data.header, a.data.urlOrData, params.resolution); const traj = await trajectoryFromG3D(data).runInContext(ctx); a.data.cache[params.resolution] = traj; return new SO.Molecule.Trajectory(traj, { label: a.label, description: a.description }); }); } }); export const LoadG3D = StateAction.build({ display: { name: 'Load Genome 3D (G3D)', description: 'Load G3D file from the specified URL.' }, from: SO.Root, params: { url: ParamDefinition.Text('') } })(({ params, state }, ctx) => Task.create('Genome3D', taskCtx => { return state.transaction(async () => { if (params.url.trim().length === 0) { throw new Error('Specify URL'); } ctx.behaviors.layout.leftPanelTabName.next('data'); const trajectory = await state.build().toRoot() .apply(G3DHeaderFromUrl, { url: params.url }) .apply(G3DTrajectory) .commit(); await defaultStructure(ctx, { trajectory }); }).runInContext(taskCtx); })); export const G3DFormat = PluginBehavior.create({ name: 'g3d', category: 'misc', display: { name: 'G3D', description: 'G3D Format Support' }, ctor: class extends PluginBehavior.Handler { register() { this.ctx.state.data.actions.add(LoadG3D); objectForEach(G3dSymbols, s => DefaultQueryRuntimeTable.addSymbol(s)); this.ctx.managers.lociLabels.addProvider(G3dLabelProvider); } unregister() { this.ctx.state.data.actions.remove(LoadG3D); objectForEach(G3dSymbols, s => DefaultQueryRuntimeTable.removeSymbol(s)); this.ctx.managers.lociLabels.removeProvider(G3dLabelProvider); } } });