From 11d5e301f39149910b5cd1dfa21ef082af40add1 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Sun, 24 May 2020 17:44:29 +0200 Subject: [PATCH] xtc format support + build tweaks --- src/mol-model-formats/structure/xtc.ts | 34 +++++++++++++++++++++++ src/mol-plugin-state/formats/structure.ts | 15 ++++++++++ src/mol-plugin-state/transforms/model.ts | 20 +++++++++++++ webpack.config.common.js | 5 ++-- webpack.config.js | 3 +- 5 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 src/mol-model-formats/structure/xtc.ts diff --git a/src/mol-model-formats/structure/xtc.ts b/src/mol-model-formats/structure/xtc.ts new file mode 100644 index 000000000..759e38bc5 --- /dev/null +++ b/src/mol-model-formats/structure/xtc.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Task } from '../../mol-task'; +import { XtcFile } from '../../mol-io/reader/xtc/parser'; +import { Coordinates, Frame, Time } from '../../mol-model/structure/coordinates'; +import { Cell } from '../../mol-math/geometry/spacegroup/cell'; + +export function coordinatesFromXtc(file: XtcFile): Task<Coordinates> { + return Task.create('Parse XTC', async ctx => { + await ctx.update('Converting to coordinates'); + + const deltaTime = Time(file.deltaTime, 'step'); + const offsetTime = Time(file.timeOffset, deltaTime.unit); + + const frames: Frame[] = []; + for (let i = 0, il = file.frames.length; i < il; ++i) { + frames.push({ + elementCount: file.frames[i].count, + // TODO: + cell: Cell.empty(), + x: file.frames[i].x, + y: file.frames[i].y, + z: file.frames[i].z, + time: Time(offsetTime.value + deltaTime.value * i, deltaTime.unit) + }); + } + + return Coordinates.create(frames, deltaTime, offsetTime); + }); +} diff --git a/src/mol-plugin-state/formats/structure.ts b/src/mol-plugin-state/formats/structure.ts index 7a6f24d40..cffea9967 100644 --- a/src/mol-plugin-state/formats/structure.ts +++ b/src/mol-plugin-state/formats/structure.ts @@ -41,9 +41,24 @@ export const DcdProvider = DataFormatProvider({ } }); +export const XtcProvider = DataFormatProvider({ + label: 'XTC', + description: 'XTC', + category: Category, + binaryExtensions: ['xtc'], + parse: (plugin, data) => { + const coordinates = plugin.state.data.build() + .to(data) + .apply(StateTransforms.Model.CoordinatesFromXtc); + + return coordinates.commit(); + } +}); + export const BuiltInStructureFormats = [ ['psf', PsfProvider] as const, ['dcd', DcdProvider] as const, + ['xtc', XtcProvider] as const, ] as const; export type BuildInStructureFormat = (typeof BuiltInStructureFormats)[number][0] \ No newline at end of file diff --git a/src/mol-plugin-state/transforms/model.ts b/src/mol-plugin-state/transforms/model.ts index 1a8ff6355..415072b22 100644 --- a/src/mol-plugin-state/transforms/model.ts +++ b/src/mol-plugin-state/transforms/model.ts @@ -37,8 +37,11 @@ import { trajectoryFromCifCore } from '../../mol-model-formats/structure/cif-cor import { trajectoryFromCube } from '../../mol-model-formats/structure/cube'; import { parseMol2 } from '../../mol-io/reader/mol2/parser'; import { trajectoryFromMol2 } from '../../mol-model-formats/structure/mol2'; +import { parseXtc } from '../../mol-io/reader/xtc/parser'; +import { coordinatesFromXtc } from '../../mol-model-formats/structure/xtc'; export { CoordinatesFromDcd }; +export { CoordinatesFromXtc }; export { TopologyFromPsf }; export { TrajectoryFromModelAndCoordinates }; export { TrajectoryFromBlob }; @@ -81,6 +84,23 @@ const CoordinatesFromDcd = PluginStateTransform.BuiltIn({ } }); +type CoordinatesFromXtc = typeof CoordinatesFromDcd +const CoordinatesFromXtc = PluginStateTransform.BuiltIn({ + name: 'coordinates-from-xtc', + display: { name: 'Parse XTC', description: 'Parse XTC binary data.' }, + from: [SO.Data.Binary], + to: SO.Molecule.Coordinates +})({ + apply({ a }) { + return Task.create('Parse XTC', async ctx => { + const parsed = await parseXtc(a.data).runInContext(ctx); + if (parsed.isError) throw new Error(parsed.message); + const coordinates = await coordinatesFromXtc(parsed.result).runInContext(ctx); + return new SO.Molecule.Coordinates(coordinates, { label: a.label, description: 'Coordinates' }); + }); + } +}); + type TopologyFromPsf = typeof TopologyFromPsf const TopologyFromPsf = PluginStateTransform.BuiltIn({ name: 'topology-from-psf', diff --git a/webpack.config.common.js b/webpack.config.common.js index a2e035dae..ff2aba48d 100644 --- a/webpack.config.common.js +++ b/webpack.config.common.js @@ -32,13 +32,14 @@ const sharedConfig = { ], }), new webpack.DefinePlugin({ - 'process.env.DEBUG': JSON.stringify(process.env.DEBUG) + 'process.env.DEBUG': JSON.stringify(process.env.DEBUG), + '__MOLSTAR_DEBUG_TIMESTAMP__': webpack.DefinePlugin.runtimeValue(() => `${new Date().valueOf()}`, true) }), new MiniCssExtractPlugin({ filename: 'molstar.css', }), new VersionFile({ extras: { timestamp: `${new Date().valueOf()}` }, packageFile: path.resolve(__dirname, 'package.json'), - templateString: `export const PLUGIN_VERSION = '<%= package.version %>';\nexport const PLUGIN_VERSION_DATE = new Date(<%= extras.timestamp %>);`, + templateString: `export const PLUGIN_VERSION = '<%= package.version %>';\nexport const PLUGIN_VERSION_DATE = new Date(typeof __MOLSTAR_DEBUG_TIMESTAMP__ !== 'undefined' ? __MOLSTAR_DEBUG_TIMESTAMP__ : <%= extras.timestamp %>);`, outputFile: path.resolve(__dirname, 'lib/mol-plugin/version.js') }) ], diff --git a/webpack.config.js b/webpack.config.js index 1289b72ed..16765f511 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,5 @@ const { createApp, createExample, createBrowserTest } = require('./webpack.config.common.js'); -const apps = ['viewer']; const examples = ['proteopedia-wrapper', 'basic-wrapper', 'lighting']; const tests = [ 'font-atlas', @@ -10,7 +9,7 @@ const tests = [ ]; module.exports = [ - ...apps.map(createApp), + createApp('viewer', 'molstar'), ...examples.map(createExample), ...tests.map(createBrowserTest) ] \ No newline at end of file -- GitLab