Compare commits

...

868 Commits

Author SHA1 Message Date
dsehnal
fa63209384 refactoring 2026-05-30 17:02:09 +02:00
dsehnal
f238b00ef9 transition easing, refactoring 2026-05-29 12:04:07 +02:00
dsehnal
1ac4980348 add comment 2026-05-29 10:55:35 +02:00
dsehnal
7ade6ab59b udpate ts config 2026-05-28 16:27:00 +02:00
dsehnal
cb0fb2b0b5 fix build 2026-05-28 15:56:48 +02:00
dsehnal
206ee19138 camera focus "zoom out" 2026-05-28 15:47:51 +02:00
dsehnal
43ce4ab498 improvements 2026-05-28 12:28:08 +02:00
dsehnal
57cce9f80f changelog 2026-05-27 18:27:36 +02:00
dsehnal
9be847c74b optimize camera direction 2026-05-27 18:20:25 +02:00
Alexander Rose
055dfd4946 Merge pull request #1840 from giagitom/fix-premul-rgb
Fix exported image artifacts on transparent background
2026-05-26 21:58:08 -07:00
giagitom
9de8334af5 Fix exported image artifacts on transparent background 2026-05-26 13:05:24 +02:00
Alexander Rose
57580a5e6b Merge pull request #1836 from giagitom/fix-cel-shading-ambient-color
Fix cel-shaded ambient color being stripped to luminance
2026-05-23 21:50:07 -07:00
giagitom
7da4a85459 Fix cel-shaded ambient color being stripped to luminance 2026-05-19 16:43:00 +02:00
Alexander Rose
27f251e8e4 Merge pull request #1832 from molstar/ssao-multi-fix
Fix SSAO half/quarter resolution textures for multi-scale
2026-05-17 20:15:09 -07:00
Alexander Rose
8d2a44983e remove superfluous enableAnimation param 2026-05-16 22:29:55 -07:00
Alexander Rose
63a585d88a Merge pull request #1830 from josemduarte/ms-fix-omitwater
Fix ModelServer bugs for omitWater param in surroundingLigands endpoint
2026-05-16 22:24:58 -07:00
Alexander Rose
a4b5a16fcd Merge branch 'master' into ms-fix-omitwater 2026-05-16 22:22:42 -07:00
Alexander Rose
86bf859a63 Fix SSAO half/quarter resolution textures for multi-scale 2026-05-16 22:15:12 -07:00
Alexander Rose
1b8117d3f1 Fix Volume and Isosurface getBoundingSphere ignoring instances 2026-05-10 17:18:18 -07:00
Alexander Rose
400e2bbc45 Merge pull request #1822 from corredD/codex/dot-morton-spheres 2026-05-10 08:42:22 -07:00
Jose Duarte
e2e26c7e9c Updating changelog 2026-05-09 22:28:38 -07:00
Jose Duarte
5ca9020cbf mol-model: fix water leak in surroundingLigands query
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:21:49 -07:00
Jose Duarte
ea4c411d5c model-server: fix omit_water boolean parsing for REST GET requests
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:21:49 -07:00
Alexander Rose
ba7e3fe827 Merge branch 'master' of https://github.com/molstar/molstar into pr/corredD/1822 2026-05-09 16:03:21 -07:00
Alexander Rose
8f20571a17 Merge pull request #1827 from molstar/camera-changed-event
Camera helpers
2026-05-09 16:02:30 -07:00
Alexander Rose
c25a4247e6 Merge branch 'master' of https://github.com/molstar/molstar into camera-changed-event 2026-05-09 15:57:47 -07:00
Alexander Rose
1071d3d8ba Merge pull request #1828 from molstar/instance-granularity-improvements
Instance granularity improvements
2026-05-09 15:56:36 -07:00
Alexander Rose
e8dc046570 Merge branch 'master' of https://github.com/molstar/molstar into instance-granularity-improvements 2026-05-09 15:54:00 -07:00
Alexander Rose
27f9c2aa67 Merge pull request #1829 from molstar/mesoscale-preset
Mesoscale preset
2026-05-09 15:53:29 -07:00
Alexander Rose
a4962231c8 revert 2026-05-09 15:51:05 -07:00
Alexander Rose
8833f29ce5 Merge branch 'master' of https://github.com/molstar/molstar into mesoscale-preset 2026-05-09 15:44:01 -07:00
Alexander Rose
40b6038380 type tweak 2026-05-09 15:43:04 -07:00
Armando Pellegrini
59e16e0187 Fix State.dispose() not invoking transformer dispose for live cells (#1826)
`Transformer.Definition.dispose` is documented as "automatically called
on deleting an object," but `State.dispose()` only disposed its own event
subjects and action manager — it never iterated still-live cells to call
their per-transformer dispose. Cells holding GL buffers, mesh data, etc.
only had their dispose fired on explicit deletion (e.g. `clear()`), so
any consumer that called `plugin.dispose()` without first awaiting
`plugin.clear()` retained the callback chain, the GL buffers it points
at, and any closures captured by it.

In a long-running single-page app where the user navigates between
routes that mount/unmount a Mol* viewer, this leaked roughly 25–50 MB
of process RSS per cycle even with `plugin.dispose()` correctly called.
A 20-cycle E2E mount/unmount harness on a 1AKE structure measured a
+541 MB RSS / +266 MB JS-heap delta in the unconditional-`dispose()`
case; calling `await plugin.clear()` before `plugin.dispose()` halved
the residual leak, confirming the per-cell dispose path was missing on
the unconditional `dispose()` route.

This change walks the cell tree once (post-order via the existing
`StateTree.doPostOrder` helper) and invokes the per-transformer dispose
for every still-live cell, swallowing+warning on errors so a single
faulty transformer can't prevent siblings from cleaning up. The
existing per-cell `dispose` helper is reused for consistency with
`updateNode`/`findDeletes` semantics.

Tests cover: chained transformers, sibling subtrees, throwing-dispose
isolation, and transformers without a dispose definition.

Also adds `useDefineForClassFields: false` to the jest esbuild
transform so tests can construct `State` (the `TransientTree` parameter
property + class field pattern relies on legacy class-field semantics,
which `tsc` honors via `target: es2018` but esbuild's default `esnext`
target does not).

Fixes #1825

Co-authored-by: Armando Pellegrini <tech.tools@boltz.bio>
2026-05-09 22:17:38 +02:00
Alexander Rose
ca5a50bd53 changelog 2026-05-09 12:36:38 -07:00
Alexander Rose
bccf54fabe avoid extra allocations 2026-05-09 12:36:32 -07:00
Alexander Rose
57a790544c Add mesoscale representation preset 2026-05-09 12:31:26 -07:00
Alexander Rose
df0669598c Add presets option to ObjectList param definition 2026-05-09 12:31:11 -07:00
Alexander Rose
fb912036af Merge branch 'master' of https://github.com/molstar/molstar into pr/corredD/1822 2026-05-09 08:25:26 -07:00
Alexander Rose
9efb5cd126 Add Camera.changed event and rotation/translation setter/getter 2026-05-09 08:24:26 -07:00
Alexander Rose
08a56ad6ab Instance granularity improvements
- Add `instanceGranularity: 'auto'` as a memory guard
- Honor `instanceGranularity` in `Visual.getLoci`
2026-05-09 08:10:58 -07:00
Alexander Rose
d7ad5a6e9f Fix empty transforms default in ShapeFromPly 2026-05-04 23:14:02 -07:00
Alexander Rose
86a74d1cc2 5.9.0 2026-05-03 10:45:51 -07:00
Alexander Rose
3f0f24cb99 changelog 2026-05-03 10:44:40 -07:00
Alexander Rose
b8ddc142ea schema updates 2026-05-03 00:15:31 -07:00
Alexander Rose
cccaa48589 ts6 tweaks 2026-05-03 00:12:36 -07:00
Alexander Rose
3ad355ad40 package updates 2026-05-03 00:12:23 -07:00
Alexander Rose
918186eb24 Merge pull request #1805 from molstar/proc-anim
Procedural animation
2026-05-02 16:18:22 -07:00
Alexander Rose
db4742cebf tweaks 2026-05-02 16:16:39 -07:00
Ludovic Autin
19fec3bbc1 Order DOT spheres by Morton index
Add DOT sphere impostors in Morton order so sphere LOD stride sampling remains spatially distributed.
2026-05-02 10:48:31 -07:00
Alexander Rose
7d6c77b3bd Merge branch 'master' of https://github.com/molstar/molstar into proc-anim 2026-05-02 09:34:00 -07:00
Alexander Rose
dfcc4e400d add animation support to texture-mesh geometry 2026-04-27 22:30:58 -07:00
Alexander Rose
c9734d83a2 Merge pull request #1818 from corredD/codex/fix-assembly-symmetry
Fix GraphQL POST request handling for Assembly Symmetry
2026-04-25 07:57:40 -07:00
Alexander Rose
93943cc27b changelog 2026-04-25 07:55:08 -07:00
Alexander Rose
25836b2de0 changelog 2026-04-25 07:50:28 -07:00
Alexander Rose
c6874c922d use record for headers
Co-authored-by: Copilot <copilot@github.com>
2026-04-25 07:50:21 -07:00
Ludovic Autin
0937c84f47 Fix GraphQL POST request handling 2026-04-18 22:20:57 -07:00
Alexander Rose
6a7f892d60 cleanup & changelog 2026-04-18 10:57:14 -07:00
Alexander Rose
b4cd2d0a11 Merge branch 'master' of https://github.com/molstar/molstar into proc-anim 2026-04-18 10:56:12 -07:00
Alexander Rose
2067f02830 changelog 2026-04-18 10:55:09 -07:00
Alexander Rose
6d86ada6b4 getNucleicOneLetterCode 2026-04-18 10:54:48 -07:00
Alexander Rose
f656cf09b7 Merge pull request #1813 from corredD/codex/slice-marking-optimization
Slice marking optimization
2026-04-18 10:54:14 -07:00
Alexander Rose
a891b4c551 tweaks and changelog 2026-04-18 10:50:23 -07:00
Alexander Rose
ded844c936 Merge branch 'master' of https://github.com/molstar/molstar into pr/corredD/1813 2026-04-18 10:46:58 -07:00
Alexander Rose
44b36637fd Merge pull request #1802 from molstar/ccd-bonds-deuterium
Handle CCD bonds with Deuterium atoms
2026-04-18 10:45:26 -07:00
Alexander Rose
f590bd0f0a Merge branch 'master' into ccd-bonds-deuterium 2026-04-18 10:29:12 -07:00
Alexander Rose
9474c80673 Merge pull request #1812 from molstar/8k-uhd-image-option
Add 8K UHD option to `ViewportScreenshotHelper`
2026-04-18 10:28:05 -07:00
Alexander Rose
7b48d691c8 Merge branch 'master' into 8k-uhd-image-option 2026-04-18 10:27:54 -07:00
Alexander Rose
b03146852f Merge pull request #1811 from molstar/mrc-empty-length 2026-04-18 09:34:42 -07:00
Ludovic Autin
9345f3584a Update slice marking file headers 2026-04-12 22:46:06 -07:00
Ludovic Autin
4d058aa1a8 Merge commit '94f6b864b0ede5c88b98725648178ceda5b7340b' into codex/slice-marking-optimization 2026-04-12 22:03:35 -07:00
Ludovic Autin
e7da6092aa Optimize slice marking for hover 2026-04-12 21:53:08 -07:00
David Sehnal
94f6b864b0 Fix empty PluginSpec.animations edgecase (#1810) 2026-04-12 19:37:21 +02:00
Alexander Rose
6e90447511 Add 8K UHD option to ViewportScreenshotHelper 2026-04-11 09:11:16 -07:00
Alexander Rose
b91030c4bd Handle MRC files with empty length header fields 2026-04-11 09:08:57 -07:00
dsehnal
31819dbf16 5.8.0 2026-04-03 19:28:58 +02:00
dsehnal
1665dd7d00 changelog + npm audit 2026-04-03 19:27:46 +02:00
Alexander Rose
9716fecdb9 add time only animation for exporting 2026-04-02 11:39:11 -07:00
Alexander Rose
684fd2d237 Merge branch 'master' of https://github.com/molstar/molstar into proc-anim 2026-04-01 16:34:01 -07:00
Alexander Rose
9432b9a7a7 ME: tweak size scale handling 2026-04-01 16:33:44 -07:00
Alexander Rose
3a37c95c17 scale tumble with bounding-sphere 2026-04-01 16:32:36 -07:00
Alexander Rose
6040b99c19 Merge branch 'master' of https://github.com/molstar/molstar into proc-anim 2026-04-01 14:22:50 -07:00
Alexander Rose
83bef0f0e7 proc anim panel & per-group wiggle 2026-04-01 14:22:38 -07:00
Alexander Rose
95bb3a1f81 Merge pull request #1801 from molstar/traj-static-prop-fix
Fix static model properties for trajectories
2026-04-01 10:31:29 -07:00
Alexander Rose
be677f47cb basic procedural animation 2026-03-27 12:55:00 -07:00
Alexander Rose
43bf69d09c handle ComponentBond.Entry.map changes 2026-03-27 09:35:25 -07:00
Alexander Rose
b6cc626431 cleanup 2026-03-27 09:14:46 -07:00
Alexander Rose
931fdfca9b move ccd logic to ComponentBond 2026-03-27 09:11:55 -07:00
midlik
1c10db5656 VolumeStreaming - avoid re-download on node update (#1804) 2026-03-27 11:36:14 +01:00
Paul Pillot
c4ccd8758f Replace node-fetch/@types with native fetch (#1803) 2026-03-27 08:44:29 +01:00
Alexander Rose
6c99c575bc Handle CCD bonds with Deuterium atoms 2026-03-26 16:23:32 -07:00
Alexander Rose
ae2493b6e3 Merge pull request #1798 from papillot/remove-promisify
remove utils.promisify dependency
2026-03-26 14:46:44 -07:00
Alexander Rose
bcd50c294f Merge pull request #1787 from molstar/vol-instance-slice
fix volume slice visual to handle instances
2026-03-26 14:44:31 -07:00
Alexander Rose
9c0024dbab Merge branch 'master' into vol-instance-slice 2026-03-26 14:41:42 -07:00
Alexander Rose
c15b3603c0 Merge pull request #1786 from molstar/vol-instance-refactor
volume refactoring for improved instance handling
2026-03-26 14:40:41 -07:00
Alexander Rose
70647ba972 tighter frame mode image size 2026-03-26 14:37:23 -07:00
Alexander Rose
8d19357845 reuse static props in Model._trajectoryFromModelAndCoordinates 2026-03-26 09:34:41 -07:00
Alexander Rose
8e9817c4d1 make Model.getAtomicRadii a static property 2026-03-26 09:33:32 -07:00
Alexander Rose
b16147b88c don't calculate atomic radii for fast boundary 2026-03-26 09:32:37 -07:00
Alexander Rose
9840d8f816 changelog 2026-03-25 15:35:11 -07:00
Alexander Rose
d892ccab4c fix mapping for grid image 2026-03-25 15:31:09 -07:00
Alexander Rose
65f88b3293 ensure image plane covers volume 2026-03-25 15:10:05 -07:00
Alexander Rose
9e6e5eb795 ensure image plane normal is normalized 2026-03-25 15:09:34 -07:00
Alexander Rose
2f755efeec handle voxels mapping to multiple pixels 2026-03-25 15:09:15 -07:00
Alexander Rose
012e616ec4 fix Mat4.fromPlane 2026-03-25 15:06:34 -07:00
midlik
007d0e7608 Fix areHierarchiesEqual, MVS empty selection focus, flickering tooltip (#1799)
* Fix StructureComponent.update when substructure empty

* Avoid tooltip box flickering when hovering something under it

* Fix MVS focus on empty selections

* Update CHANGELOG
2026-03-24 15:56:19 +01:00
Paul Pillot
bf313073b9 remove utils.promisify dependency
This dependency pulls a 23MB dependency graph to support nodejs v<8.0
Native alternatives exist: fs.promises, and native utils/promisify

Consistency: renaming readFile --> readFileAsync where changes were made.
2026-03-24 09:54:10 -04:00
Alexander Rose
293928f3de Merge branch 'vol-instance-refactor' of https://github.com/molstar/molstar into vol-instance-slice 2026-03-23 09:55:44 -07:00
Alexander Rose
2404f398b6 Merge branch 'master' of https://github.com/molstar/molstar into vol-instance-refactor 2026-03-23 09:55:11 -07:00
Alexander Rose
43ff6e24c8 Merge pull request #1789 from molstar/more-debug-helpers
More debug helpers
2026-03-23 09:54:24 -07:00
Alexander Rose
9e62112366 Merge branch 'master' into more-debug-helpers 2026-03-23 09:54:14 -07:00
midlik
026d6fc618 MVS VolumeStreamingExtension (#1793)
* InitVolumeStreaming refactor

* InitVolumeStreaming refactor 2

* CreateVolumeStreamingInfo autoEntries param

* MVS VolumeStreamingExtension

* Update CHANGELOG

* MVS: avoid structure focus persisting through states

* MVS VolumeStreamingExtension - collapse VolumeServer node
2026-03-21 10:32:17 +01:00
Alexander Rose
95fcd942dc refactor interior handling 2026-03-19 14:25:51 -07:00
Alexander Rose
805481db14 changelog 2026-03-19 14:06:28 -07:00
Alexander Rose
39175df025 tweaks 2026-03-19 13:55:05 -07:00
Alexander Rose
cd0f451f6b Merge branch 'master' of https://github.com/molstar/molstar into more-debug-helpers 2026-03-18 15:44:28 -07:00
Alexander Rose
fe1aa1a9bf move debug helpers to extension 2026-03-18 15:44:10 -07:00
Alexander Rose
fcfb6e6d5a Merge pull request #1788 from rjdirisio/seqres-to-sequence-toolbar
Use SEQRES to show unresolved residues in Sequence toolbar
2026-03-18 13:41:44 -07:00
Alexander Rose
c548c94575 Merge branch 'master' of https://github.com/molstar/molstar into more-debug-helpers 2026-03-18 12:50:59 -07:00
Alexander Rose
2d45f4a77c move code into getPdbxUnobsOrZeroOccResidues
- explicitely refer to mmcif enum types
2026-03-18 12:19:37 -07:00
Alexander Rose
a5ae887842 schema updates
- fix mmcif int enums
2026-03-18 12:17:28 -07:00
Ryan DiRisio
e4b53cdc6a simplify alignCompIdsToSeqres as a result of merge 2026-03-18 12:06:19 -04:00
Ryan DiRisio
c53940e67e Merge remote-tracking branch 'upstream/master' into seqres-to-sequence-toolbar 2026-03-18 12:01:10 -04:00
Alexander Rose
6d61745f0f Merge pull request #1794 from rjdirisio/fix-return-alignment-return-type
Fix return `alignment.trace()` return to match return type
2026-03-18 08:59:26 -07:00
Alexander Rose
46d86d93b0 tweak unknown residue handling in blosum scoring 2026-03-18 08:55:48 -07:00
Ryan DiRisio
11772b64fb update header 2026-03-18 11:18:07 -04:00
Ryan DiRisio
dbc8ab00c6 Merge branch 'master' into fix-return-alignment-return-type 2026-03-18 11:14:45 -04:00
Ryan DiRisio
015fad4371 trace() returns string[] rather than string 2026-03-18 11:13:07 -04:00
Ryan DiRisio
71a484586f Throw error if getEntityId not called before getEntityIdForChain 2026-03-18 11:02:15 -04:00
Ryan DiRisio
f0b06ee746 Merge remote-tracking branch 'upstream/master' into seqres-to-sequence-toolbar 2026-03-17 15:52:29 -04:00
Ryan DiRisio
b0694b886b add entity_poly_seq check in unobs test 2026-03-17 15:51:31 -04:00
Ryan DiRisio
eaf47b3169 rm excess comments 2026-03-17 15:41:48 -04:00
Ryan DiRisio
ad9046fcf2 regression tests for 1NSA 2026-03-17 15:25:07 -04:00
Ryan DiRisio
eabe4d46bc tests for SEQRES 2026-03-17 15:20:44 -04:00
Ryan DiRisio
003c5f8fb7 update file headers 2026-03-17 15:13:24 -04:00
Ryan DiRisio
68748a4a94 use -1 for unaligned residue 2026-03-17 15:11:44 -04:00
Ryan DiRisio
9bd6b8195d factor out initialLabelSeqId w/ comment 2026-03-17 15:06:53 -04:00
Ryan DiRisio
05848b651c factor out computeSeqresAlignments helper function 2026-03-17 15:02:57 -04:00
Ryan DiRisio
0a8f87dd9f factor out getEntityPolySeq
add to helperCategories
2026-03-17 15:00:09 -04:00
Ryan DiRisio
925aaa701d remove hasSeqRes, add debug log for seqres block 2026-03-17 14:53:49 -04:00
Ryan DiRisio
5be599bad4 Update CHANGELOG.md 2026-03-17 14:48:29 -04:00
Tianzhen Lin (Tangent)
e22ce53e65 Fix circular dependency crash in bundlers (esbuild, Rolldown) (#1792)
* Fix circular dependency crash in bundlers (esbuild, Rolldown)

StateTransforms uses `import * as X` namespace imports that are
assigned as object properties at module construction time. When a
bundler concatenates modules into a single scope and reorders their
initialization (as esbuild and Rolldown do), the namespace variable
can still be undefined when the object literal is evaluated, causing
a runtime crash:

  Cannot read properties of undefined (reading 'ModelUnitcell3D')

Replace direct property assignments with lazy getters so that
namespace imports are resolved at access time rather than at
construction time. This preserves the existing public API — callers
still use `StateTransforms.Representation.CreateStructureRepresentation3D`
— while making the code safe regardless of module evaluation order.

Fixes #1791

* Add changelog entry and contributor for circular dependency fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:38:48 +01:00
Alexander Rose
4c49431027 fix imports 2026-03-08 22:33:41 -07:00
Alexander Rose
4192d82ef3 file reorg 2026-03-08 22:25:27 -07:00
Alexander Rose
ce220737f2 description 2026-03-08 22:21:57 -07:00
Alexander Rose
eeb7cd2c52 add more debug helpers
- clip-object
- direct-volume
- image
- mesh
2026-03-08 22:18:30 -07:00
Alexander Rose
748111beb2 rename bounding-sphere helper and add separate debug helper 2026-03-08 22:16:59 -07:00
Alexander Rose
1f7d41c653 improve helpers drawing order 2026-03-08 22:14:46 -07:00
Alexander Rose
b9430ff387 add lines builders (box, plane, sphere) 2026-03-08 22:13:47 -07:00
Alexander Rose
6591bab035 Fix clip-object transform due to missing axis normalization 2026-03-07 10:21:21 -08:00
Ryan DiRisio
4da446aec2 skip non-polymer atoms 2026-03-02 13:01:02 -05:00
Ryan DiRisio
25c170e36d use global alignment that exists in the repo 2026-03-02 11:05:31 -05:00
Ryan DiRisio
eba18d1dce first pass at getting SEQRES data into sequence toolbar 2026-03-02 10:22:03 -05:00
Alexander Rose
2c87d01a5e fix volume slice visual to handle instances 2026-03-01 15:01:42 -08:00
Alexander Rose
e41a2baa32 volume refactoring for improved instance handling
- add Volume._localPropertyData
- move Volume.periodicity to Grid
- add optional Volume.parent
- fix Volume.getBoundingSphere to account for instances
- add periodicRange mode to VolumeInstances PluginStateTransform
- include currentVolume in VolumeViosual.setUpdateState
2026-03-01 14:56:53 -08:00
Alexander Rose
c297017749 Fix detecting sidechain-only structures as coarse-grained 2026-03-01 11:01:42 -08:00
Alexander Rose
9a0fc1faa6 changelog 2026-03-01 11:00:00 -08:00
Alexander Rose
424513f23c Merge branch 'master' of https://github.com/molstar/molstar 2026-03-01 10:58:57 -08:00
zachcp
895d672589 feat: add putty mvs to molstar (#1783) 2026-03-01 16:55:19 +01:00
Alexander Rose
0c6253ed16 formating 2026-02-28 18:23:41 -08:00
Alexander Rose
da97cd20aa 5.7.0 2026-02-28 13:43:11 -08:00
Alexander Rose
ca6d73e048 changelog 2026-02-28 13:41:30 -08:00
Alexander Rose
88b79deefa package updates
- set min node to v22
- added globals for eslint v10
2026-02-28 13:40:38 -08:00
Alexander Rose
d756e2e195 schema updates 2026-02-28 13:22:39 -08:00
Alexander Rose
2ce126a8f5 update cif-core schema 2026-02-28 13:19:05 -08:00
Alexander Rose
01e95dada0 ignore some lint commits in git blame 2026-02-28 13:16:59 -08:00
Alexander Rose
1c024f0943 Merge pull request #1778 from molstar/polyhedron
Polyhedron
2026-02-22 12:32:22 -08:00
Alexander Rose
5901e3d6a1 Merge branch 'master' into polyhedron 2026-02-22 12:29:02 -08:00
Alexander Rose
0cfe1cec66 Merge pull request #1784 from molstar/guard-xr-policy
Guard against `xr-spatial-tracking` blocked in `Permissions-Policy`
2026-02-22 12:28:44 -08:00
Alexander Rose
c1930e4142 Merge pull request #1771 from molstar/basic-streamlines
Basic streamlines
2026-02-22 12:13:39 -08:00
Alexander Rose
71375d908f Guard against xr-spatial-tracking blocked in Permissions-Policy 2026-02-22 11:31:08 -08:00
Alexander Rose
728b87d4e4 Merge branch 'master' of https://github.com/molstar/molstar into polyhedron 2026-02-21 20:58:32 -08:00
Alexander Rose
9c17698a8a rename visual to include "coordination" 2026-02-21 20:57:43 -08:00
Alexander Rose
625381c446 exclude hydrogens 2026-02-21 20:57:20 -08:00
Alexander Rose
da949a245e Merge pull request #1776 from molstar/element-parsing-fixes
Element parsing fixes
2026-02-19 20:40:44 -08:00
Alexander Rose
7000bdd15d Merge branch 'master' into element-parsing-fixes 2026-02-19 20:40:28 -08:00
Alexander Rose
adcf6a6fa8 Merge pull request #1777 from molstar/metal-coordination-style
Add `metalCoordination` style param
2026-02-19 20:40:07 -08:00
Alexander Rose
b70af9f178 Merge branch 'master' into metal-coordination-style 2026-02-19 20:39:40 -08:00
Alexander Rose
e5bdcfd781 Merge pull request #1781 from molstar/fix-unit-symmetry-groups
Fix `unitSymmetryGroups` for representations with `includeParent`
2026-02-18 20:46:15 -08:00
Alexander Rose
6049705224 Fix unitSymmetryGroups for representations with includeParent enabled 2026-02-16 19:57:56 -08:00
Alexander Rose
273d50d403 cleanup coordination data model 2026-02-15 20:59:52 -08:00
Alexander Rose
333ea724d6 Merge pull request #1779 from giagitom/text-improvements
Additional text improvements
2026-02-15 13:32:20 -08:00
giagitom
e96dca91ef Add author to text.ts 2026-02-15 13:36:34 +01:00
giagitom
41a0048f64 Simplify text frag shader, remove near-clip discard, fix bounding sphere padding 2026-02-15 13:33:44 +01:00
Alexander Rose
5e97b05bd2 Add Polyhedron representation showing coordination sites 2026-02-15 00:10:00 -08:00
Alexander Rose
ebc6b2acce Add Structure.coordination sites 2026-02-15 00:09:46 -08:00
Alexander Rose
8372408d9c Add convexHull helper 2026-02-15 00:09:17 -08:00
Alexander Rose
2c6822f5ab Add metalCoordination style param (dashed, solid) for bonds 2026-02-15 00:06:00 -08:00
Alexander Rose
7efbf46e7a Merge pull request #1774 from giagitom/text-improvements
Text label improvements
2026-02-14 23:34:01 -08:00
Alexander Rose
b6d6a518d3 Add more element-pair thresholds for bonding (Ag-S, CoSb, Ga-F) 2026-02-14 23:21:17 -08:00
Alexander Rose
2d690268f9 Handle additional elements in guessElementSymbol* (As, Li, Ga) 2026-02-14 23:20:54 -08:00
Alexander Rose
e0c794b557 Detect metal-coordination when parsing pdb 2026-02-14 23:20:25 -08:00
Alexander Rose
f91f445631 Fix parsing of single charge type_symbols (e.g., N+) in cif-core 2026-02-14 23:20:05 -08:00
giagitom
1cc367c8d8 Fix head rotation for clip-space billboard offset 2026-02-15 01:09:42 +01:00
giagitom
8c6969206d Update copyright years to 2026 2026-02-15 00:59:48 +01:00
Alexander Rose
c0479e3d46 Merge branch 'master' of https://github.com/molstar/molstar into basic-streamlines 2026-02-14 13:41:03 -08:00
Alexander Rose
22e92b38c6 Merge pull request #1775 from molstar/vertex-size
Add `vertex` and `vertexInstance` granularity for size
2026-02-14 13:40:21 -08:00
giagitom
5741709023 Hard discard near clip, revert attachment, cleanup nearFade 2026-02-14 21:11:56 +01:00
Alexander Rose
2265fc02cc per-point tube size 2026-02-14 08:56:04 -08:00
Alexander Rose
64180bef36 add min separation 2026-02-14 08:54:12 -08:00
Alexander Rose
be3caef6e9 Add vertex and vertexInstance granularity for size
- Geometry export: Support vertex-based sizing
- Add `transform` and `domain` parameters to volume-value size theme
2026-02-14 08:26:48 -08:00
giagitom
71a2f71866 Text label improvements
- Fix label attachment inversion (top/bottom and left/right)
- Improve label background vertical centering
- Add label near-clip fade out
- Handle label depth variant for correct transparent background and near fade
- Draw border under text using fragment depth to prevent overlap on adjacent characters
- Clamp border width to avoid exceeding SDF range
- Increase font atlas quality (2x font size multiplier)
- Use clip-space billboard rendering to avoid perspective distortion
2026-02-14 10:53:49 +01:00
David Sehnal
3c6152054e fix TextCtrl (#1773)
* fix TextCtrl

* header
2026-02-12 17:53:02 +01:00
Alexander Rose
080d649bf9 Streamlines support
- Add basic calculation method
 - Add custom-volume-property
 - Add representation with lines and tube-mesh visuals
2026-02-08 19:28:19 -08:00
Alexander Rose
2852b09c77 Merge pull request #1770 from molstar/line-strips 2026-02-08 15:09:12 -08:00
Paul Pillot
5e53467541 Tmalign perf tweaks (#1756)
* add computeCenter util fn

This is more efficient than using the CentroidHelper patterns.

Time improvement: 135ms --> 113ms on 4JV6/3T5I benchmark

* kabsch received array of indices

instead of array of coordinates which requires to build intermediary arrays in each caller.

* Reuse of Vec3 objects

- Avoid Vec3.create in loops
- use Vec3.squaredDistance instead of repeated double index access
- For simplifying TS manipulations, type xa, ya as Vec3 arrays.

* Reuse Positions

MinimeRmsdPositions.empty was called twice in kabsch fn. A unique call is now done with the full length and the same object is reused.
The length property is passed to ensure that only the portion that contains the required coordinates is used.

* simpler hypothenuse implementation

* missing break statements

- when score has not improved, we don't need to run again with the same parameters
- when the number of residues passing the cutoff is lower than 3, we don't need to run again with stricter cutoffs

* hint at float array

* update headers

* cache transformed coordinates, align indices

* replace ndpwScore with ndpwStructure

ndpwScore was creating an intermediate 2D array which is already cached in ndpwStructure

* trimmedKabschWithTransformedCoordinates

avoid recomputing transformed coordinates (as in trimmedKabsch) when they are already available

* cache rmsdResult and rmsdState

bestTransform must not keep a reference to result.bTransform because its value would change each time kabsch function is run.

* swap shortest structure to B

All transforms are made against the coordinates for structureB when yt is computed.

* reafactor: generalize usage of incremental sequence

Previous implementation was relying on tmpAlignA to hold the indices. It was conflictin in `tryGaplessThreading` with the call to `extendFromSeed`.
A distinct buffer has been created.

* refactor: preallocate dp arrays in constructor, uniform usage of typed arrays

* wrap tm-align in a task + useOverlay

* Skip fragment based strategy if similarity is good

Fragment based alignment takes up most of the computation time due to the O(n3) complexity of aligning fragments of different length. When the alignment is already good, this procedure does not yield improved results (observed also by the original authors).

The threshold for "similar structure" is set to a TM-score of 0.5 according to litterature.
Because it's possible to align 2 structures of very different length, and because the TM-score is normalized using the sequence length, it's important to change the reference for computation from a random choice (sequence A), to the minimal sequence length. This is consistent with the equations from the original TM-align publication (Lmin is used in scoring).

Note that the code already ensures that the shortest sequence is B (less iterations), but this commit makes the min sequence length explicit.
2026-02-08 14:49:14 +01:00
Alexander Rose
42dc579ddb changelog 2026-02-07 15:21:06 -08:00
Alexander Rose
890c758585 Geometry export
- Fix vertex-based coloring for non-mesh geometries
- Support line-strips
2026-02-07 15:20:58 -08:00
Alexander Rose
e6c77069df add frenet-frames helper 2026-02-07 15:20:14 -08:00
Alexander Rose
e7ecf98f13 add line-strips to lines geo 2026-02-07 15:19:25 -08:00
Alexander Rose
70ad32f62d Merge pull request #1769 from molstar/split-vol-visual
split volume visual code
2026-02-07 13:52:28 -08:00
Alexander Rose
69fe452055 split volume visual code 2026-02-07 10:43:12 -08:00
Alexander Rose
9edeb84f4e default to linear 2026-02-01 22:54:14 -08:00
Alexander Rose
e1db3114c8 Fix missing usePalette support in MeshExporter 2026-02-01 22:50:50 -08:00
Alexander Rose
8724badcb6 fix volume valueRef getData to select roots 2026-02-01 22:03:28 -08:00
Alexander Rose
d413f74526 Merge pull request #1764 from molstar/pqr-support
PQR support
2026-02-01 21:59:45 -08:00
Alexander Rose
6752108c5f changelog 2026-02-01 21:55:21 -08:00
Alexander Rose
9302fdadb9 undo adding pqr to mvs 2026-02-01 21:22:44 -08:00
Alexander Rose
f7048c7535 Merge branch 'master' of https://github.com/molstar/molstar into pqr-support 2026-02-01 21:20:57 -08:00
Alexander Rose
3252a3f0f3 Merge pull request #1765 from molstar/custom-volume-property 2026-02-01 12:48:28 -08:00
Alexander Rose
6805194d48 file headers 2026-01-31 17:33:52 -08:00
Alexander Rose
acf0dceb47 add CustomVolumeProperty 2026-01-31 17:30:43 -08:00
Alexander Rose
c53f500da6 add pqr support 2026-01-31 17:15:17 -08:00
midlik
defc04278e MVSData.toMVSX (#1763) 2026-01-29 16:51:54 +01:00
Alexander Rose
aa4d5e78a7 Merge pull request #1757 from giagitom/improve-outlines
disable transparent outline when near to solid mesh
2026-01-26 20:05:29 -08:00
Alexander Rose
df3a432afd Merge branch 'master' into improve-outlines 2026-01-25 22:38:19 -08:00
Alexander Rose
1b339d18cc Merge pull request #1762 from molstar/trackball-animation-axis
add axis param to trackball spin & rock animation
2026-01-25 22:37:24 -08:00
Alexander Rose
c4650c91a8 Merge branch 'master' into trackball-animation-axis 2026-01-25 22:37:15 -08:00
Alexander Rose
e3c4f19563 Merge pull request #1761 from molstar/fix-color-smoothing 2026-01-25 22:26:35 -08:00
Alexander Rose
85780a5d6a add axis param to trackball spin & rock animation 2026-01-24 12:11:50 -08:00
Alexander Rose
aab70e2ff0 Color smoothing fixes (#1747)
- use correct instance for non instance-type
- never transform for non instance-type
- add extra radius to gaussian surface boundingsphere
2026-01-24 12:09:04 -08:00
dsehnal
e859f497f1 5.6.1 2026-01-23 15:42:44 +01:00
dsehnal
6a9fed56f3 changelog 2026-01-23 15:40:54 +01:00
dsehnal
d7c2505852 npm audit 2026-01-23 15:40:31 +01:00
midlik
754dfeab91 Fix MVSAnnotationStructureComponent not updating properly (#1759)
* Fix `MVSAnnotationStructureComponent` not updating properly when parent structure changes

* lint

* fix build
2026-01-23 13:55:41 +01:00
Alexander Rose
d3b02df5b9 Disable occlusion culling in ImagePass (#1758) 2026-01-20 06:53:26 -08:00
giagitom
3d95ed729c disable transparent outline when near to solid mesh 2026-01-19 19:59:07 +01:00
Alexander Rose
9cbb4414e0 5.6.0 2026-01-18 12:11:39 -08:00
Alexander Rose
79fcfe50bc changelog 2026-01-18 11:44:42 -08:00
Alexander Rose
216d16456b package updates 2026-01-18 11:43:06 -08:00
Alexander Rose
822aaa99b0 Merge pull request #1755 from molstar/seqres-entity-lipids
Improve SEQRES use and more lipid names
2026-01-18 10:53:07 -08:00
Alexander Rose
2c683ab77d Merge pull request #1754 from molstar/fix-bounding-sphere-reuse
fix boundingSphere reuse in structure visuals
2026-01-18 10:52:44 -08:00
Alexander Rose
2ef5af6881 Merge pull request #1753 from molstar/remove-fence-canvas3d
remove fence from Canvas3D.render
2026-01-18 10:47:29 -08:00
Alexander Rose
36f18be042 add lipid components names used in amber ff 2026-01-17 18:34:32 -08:00
Alexander Rose
f093a3ab37 use PDB seqres record to deduce entity information 2026-01-17 18:31:43 -08:00
Alexander Rose
74cd42117b fix boundingSphere reuse in structure visuals
- was triggering extra calculation
- add hasBoundingSphere method to geometries
2026-01-17 17:34:53 -08:00
Alexander Rose
bb4a4e6102 remove fence from Canvas3D.render
- causes issues when the CPU is busy
- interfers with `requestAnimationFrame`
2026-01-17 17:08:13 -08:00
Alexander Rose
24a3167f9b Merge branch 'master' of https://github.com/molstar/molstar 2026-01-17 16:55:07 -08:00
Alexander Rose
214e1c20ca ignore missing plugin-state-animation 2026-01-17 16:55:02 -08:00
Alexander Rose
33cab6ddad Merge pull request #1752 from sbittrich/los
Non-covalent interactions: Prevent self-occlusion on quaternary amines
2026-01-17 16:48:55 -08:00
Alexander Rose
f4b2826bc7 Merge branch 'master' into los 2026-01-17 16:45:34 -08:00
Alexander Rose
ebaa9f2e56 use eachIntraBondedAtom (@sbittrich) 2026-01-17 16:44:36 -08:00
Alexander Rose
812b75a034 Merge pull request #1750 from sbittrich/master
Fix outline postprocessing artifacts
2026-01-17 16:34:20 -08:00
Alexander Rose
3b02a5f5ec Merge pull request #1742 from giagitom/add-wireframe-structure-visuals
Add structure wireframe visuals on molecular and gaussian surfaces
2026-01-17 13:13:12 -08:00
Alexander Rose
657d2eb1c5 Merge branch 'master' into add-wireframe-structure-visuals 2026-01-17 13:10:01 -08:00
Alexander Rose
25d87dd14d params tweaks 2026-01-17 13:09:24 -08:00
Sebastian
d2605e6e3d Merge remote-tracking branch 'upstream/master' into los
# Conflicts:
#	CHANGELOG.md
2026-01-16 14:52:47 +01:00
Sebastian
b21ebe0f55 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	CHANGELOG.md
2026-01-16 14:51:56 +01:00
Sebastian Bittrich
2693fe8b7e actually cache __srcIndexArray__ (#1751)
Co-authored-by: Sebastian <bittrich@pharmai-discovery.com>
2026-01-16 13:15:08 +01:00
Sebastian
45279a6520 nci: prevent self-occlusion on quat amines 2026-01-16 11:36:30 +01:00
Sebastian
22f9b1a7a1 fix outline postprocessing artifacts (closes #1749) 2026-01-16 09:15:04 +01:00
zachcp
8325a58e25 20261110 hex fix clean (#1746) 2026-01-12 08:14:14 +01:00
midlik
0acc508a8f MVS text_format and group_by_fields (#1744)
* MVS: text_format

* MVS: group_by_fields params for label_from_*

* refactor

* Update CHANGELOG

* Refactor fstrings (FormatTemplate)

* Move fstrings (FormatTemplate) to src/mol-util/formatting.ts

* FormatTemplate: fix parsing of fillChar ':'

* file rename
2026-01-10 12:50:37 +01:00
giagitom
2af0cd9d6f Add structure wireframe visuals on molecular and gaussian surfaces 2026-01-04 12:57:27 +01:00
Alexander Rose
304858fcba Merge pull request #1741 from giagitom/improve-ssao-boundaries
Improve ssao boundaries
2026-01-03 09:24:07 -08:00
giagitom
ade027911c improve occlusion evaluation at boundaries 2026-01-03 17:13:33 +01:00
David Sehnal
a97e647f7a Fix to_mmCIF writing duplicate categories under certain conditions (#1739) 2026-01-03 09:59:47 +01:00
Alexander Rose
008bed0233 fix transparent ssao handling 2026-01-02 17:33:07 -08:00
Alexander Rose
bb4c04f3b9 fix ssao darkening
- instead of clamping offscreening pixels, skip samples
2026-01-02 09:48:40 -08:00
Alexander Rose
62997e5972 Merge pull request #1737 from molstar/pcg
stable random numbers (PCG)
2025-12-31 12:16:54 -08:00
Alexander Rose
a20e7bb40d Fix SSAO darkening when sampling background/offscreen pixels 2025-12-31 12:14:35 -08:00
Alexander Rose
2acfac4c85 changelog 2025-12-31 11:35:04 -08:00
Alexander Rose
a1a9d87a54 fix missing scaling 2025-12-30 23:11:53 -08:00
Alexander Rose
1ab71cc487 calculate random hemisphere vectors on demand 2025-12-30 22:39:48 -08:00
Alexander Rose
a8b19f5f3c use blue noise for ssao sample vectors
- properly sample on sphere (not in box)
2025-12-30 21:41:09 -08:00
David Sehnal
4661a4a5f0 Only show "already registered transformer" warnings in non-production builds (#1732) 2025-12-30 16:00:19 +01:00
David Sehnal
2c40abc808 Fix label_seq_id assignment in PDB parser (#1731)
* Fix `label_seq_id` assignment in PDB parser when insertion codes are present

* tweak

* changelog

* typo

* SEQRES detection in PDB parser
2025-12-30 15:59:40 +01:00
Alexander Rose
10d7bcf4c0 stable random numbers (PCG)
- ME grayscale colors
- dot offset
- SSAO hemisphere vectors
2025-12-29 20:08:10 -08:00
Alexander Rose
5f8e4e6913 Merge pull request #1735 from molstar/volsurf-12-25
volume & surface improvements
2025-12-28 21:10:32 -08:00
Alexander Rose
94fa9f124a pr feedback optim 2025-12-28 21:02:31 -08:00
David Sehnal
3e70251f38 Viewer QoL (#1734)
* Viewer QoL

* docs
2025-12-28 19:26:33 +01:00
Alexander Rose
66ed6cfa94 type fix 2025-12-27 14:39:49 -08:00
Alexander Rose
d82b6e8d0d changelog 2025-12-27 14:33:30 -08:00
Alexander Rose
5a5f6867b9 support volume floodfill before surface extraction
- for isosurface, molecular-surface, gaussian-surface
2025-12-27 14:29:05 -08:00
Alexander Rose
5cd5fc09f5 support includeParent for gaussian-surface
- disables GPU support
2025-12-27 14:15:28 -08:00
Alexander Rose
17528d5ca2 tweak gaussian-density smothness default range 2025-12-27 14:10:07 -08:00
midlik
e658a11947 MVS misc fixes (#1733)
* MVS - fix carbohydrate sizing

* MVS: color_from_uri and color_from_source take selector parameter

* MVS: Add `keepCameraOrientation` option for loading functions

* MVS: Remove dead code

* MVS: minor refactor (SelectorT)

* PR1733 feedback
2025-12-24 14:41:49 +01:00
dsehnal
4ac6f5c202 5.5.0 2025-12-22 12:50:36 +01:00
dsehnal
5726515707 changelog 2025-12-22 12:48:58 +01:00
Alexander Rose
f2ee7d1470 fix unit hash collision (#1729)
* fix unit hash collision

* cleanup

* name tweak
2025-12-22 09:53:29 +01:00
Alexander Rose
4140412e06 schema updates 2025-12-21 16:16:02 -08:00
Alexander Rose
44ed142521 package updates 2025-12-21 16:11:31 -08:00
Alexander Rose
1ae0bbc150 Merge pull request #1727 from molstar/geo-interior-coloring
per-geometry interior coloring
2025-12-21 16:03:43 -08:00
Alexander Rose
8213611293 fix bumpiness for solid interior 2025-12-21 16:00:17 -08:00
Alexander Rose
2697634a9f Merge branch 'master' of https://github.com/molstar/molstar into geo-interior-coloring 2025-12-21 15:07:42 -08:00
Alexander Rose
d7ba9e0c61 typo 2025-12-21 15:07:01 -08:00
Alexander Rose
c99c4342b7 Merge pull request #1728 from molstar/improvements-251221
General Improvements
2025-12-21 15:01:29 -08:00
Alexander Rose
f410e27d1a use camelCase 2025-12-21 14:57:46 -08:00
Alexander Rose
e6d54412cf typo 2025-12-21 14:51:48 -08:00
Alexander Rose
6238684819 tweak residue-charge coloring
- add charmm/amber protonation variants
- add common modified residues from CCD
- remove unrelated links
2025-12-21 14:33:10 -08:00
dsehnal
ea07cd89de better canvas background handling 2025-12-21 16:15:56 +01:00
dsehnal
a7330f40d7 MVS getCurrentMVSSnapshot util 2025-12-21 15:38:57 +01:00
dsehnal
92c55ffe35 Tweak ResidueChargeColorTheme params 2025-12-21 12:10:29 +01:00
David Sehnal
c21ba08fc7 Viewer improvements (#1725)
* separate exxtensions file

* subscribe method on the Viewer object

* export lib

* Add viewer.structureInteraction

* MVS tryGetPrimitivesFromLoci util

* param select indicator

* tweaks

* mapped control icon

* docs and tweaks

* viewer color themes

* tweak

* typo

* pr feedback
2025-12-21 11:35:49 +01:00
Alexander Rose
ba3a716900 interior coloring
- replace global with per-geometry system
2025-12-20 16:21:49 -08:00
Alexander Rose
3133dc1543 Fix flipSided for meshes 2025-12-20 13:55:06 -08:00
dsehnal
fe2541f9e8 tweak package.json 2025-12-19 13:19:30 +01:00
ddelalamo-takeda
27af73f97f Add TM-align structure alignment algorithm (#1723)
* Delete docs/docs/plugin/superposition.md

* Add TM-align structure alignment algorithm

Implement TM-align for structure-based protein alignment, providing an
alternative to sequence-based superposition methods. TM-align finds optimal
structural alignments regardless of sequence similarity using TM-score.

New features:
- Core TM-align algorithm (src/mol-math/linear-algebra/3d/tm-align.ts)
  - TM-score calculation with length-independent normalization
  - Dynamic programming for optimal alignment
  - Gapless threading and fragment-based initialization
  - Multiple refinement passes for accuracy (~97.7% of US-align reference)

- High-level wrapper (src/mol-model/structure/structure/util/tm-align.ts)
  - tmAlign() function accepting StructureElement.Loci inputs
  - Returns transformation matrix, TM-scores, RMSD, and alignment

- BasicWrapper API (src/examples/basic-wrapper/)
  - tmAlign(pdbId1, chain1, pdbId2, chain2, color1?, color2?)
  - sequenceAlign() - sequence-based superposition
  - loadStructures() - load without alignment
  - Example HTML pages demonstrating usage

- UI integration (src/mol-plugin-ui/structure/superposition.tsx)
  - TM-align option in superposition panel

References:
Zhang Y, Skolnick J. Nucl Acids Res 33, 2302-9 (2005)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Delete src/examples/basic-wrapper/index.html

* changing reference test case

* Restoring src/examples/basic-wrapper/index.html

* Addressing comments in pull request

* Authorship added

---------

Co-authored-by: Diego del Alamo <diego.delalamo@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 13:18:11 +01:00
Lukas Polak
e9a442ca6e Add Residue Charge color scheme (#1722)
* Add charged residue color scheme

* Changelog + file header

* Address PR comments

* Remove residue-name.ts contribution info

* PR suggestion

* Changelog reference PR
2025-12-19 13:15:51 +01:00
Alexander Rose
e86e282bb4 Fix missing gl.flush for async picking 2025-12-16 21:24:23 -08:00
Alexander Rose
213506dff0 Fix program not compiled for sync picking 2025-12-16 21:23:22 -08:00
Alexander Rose
bc7aa7c9aa Fix webgl1 shader syntax 2025-12-16 21:21:58 -08:00
Alexander Rose
b234bf8890 Fix molecular-surface when probe diameter smaller then resolution 2025-12-14 10:30:21 -08:00
Alexander Rose
36b4dcf7a8 Fix molecular-surface "auto" quality params not hidden 2025-12-13 22:07:11 -08:00
Alexander Rose
0e843c20cc 5.4.2 2025-12-07 11:00:41 -08:00
Alexander Rose
ecaf19c5fb changelog 2025-12-07 10:59:26 -08:00
Alexander Rose
f024aeef2c schema updates 2025-12-07 10:58:03 -08:00
Alexander Rose
9d9985f117 package updates 2025-12-07 10:57:55 -08:00
Alexander Rose
a0f7349ef6 reduce automatic quality on standalone HMD devices 2025-12-06 10:50:00 -08:00
Alexander Rose
01407427d2 Merge pull request #1714 from giagitom/postprocessing-improvements
postprocessing improvements
2025-12-06 10:31:39 -08:00
Alexander Rose
3dee03d9b6 cleanup & changelog 2025-12-06 10:26:59 -08:00
Alexander Rose
737f6593be Merge pull request #1712 from molstar/import-tweaks
Import tweaks
2025-12-06 10:15:41 -08:00
giagitom
068e10dd40 fix whitespaces 2025-12-05 11:16:27 +01:00
giagitom
c1ba5248b0 postprocessing improvements 2025-12-04 16:06:30 +01:00
Alexander Rose
4af0f22ac0 remove dependency between mol-util and mol-io 2025-11-23 19:19:17 -08:00
Alexander Rose
25a67e1176 remove dependency between vec4 and sphere3d 2025-11-23 19:09:06 -08:00
Alexander Rose
a8fcd501d6 remove dependency between mol-util and mol-canvas3d 2025-11-23 19:05:48 -08:00
Alexander Rose
573ee92889 remove dependency between mol-util and mol-script 2025-11-23 19:04:58 -08:00
Alexander Rose
2558d6fada remove dependency between mol-math and mol-geo 2025-11-23 19:01:11 -08:00
Alexander Rose
2cf3f8d62b move DensityTextureData type out of shared module
- not reused, depends on mol-gl
2025-11-23 19:00:12 -08:00
Alexander Rose
589d89b0d5 remove import from mol-geo in mol-gl
- too many dependencies
- not usefull, mostly for documentation
2025-11-23 18:58:31 -08:00
Alexander Rose
7cc7b77460 add missing method in gl shim 2025-11-23 18:55:40 -08:00
Alexander Rose
e8a9995bef use more direct imports
- avoid importing from re-exports
- helps to create smaller files with some bundlers
2025-11-23 18:55:11 -08:00
Alexander Rose
74ff283e00 5.4.1 2025-11-16 10:18:09 -08:00
Alexander Rose
1ecb960b82 changelog 2025-11-16 10:17:14 -08:00
Alexander Rose
387d59f97b Merge branch 'master' of https://github.com/molstar/molstar 2025-11-16 10:13:12 -08:00
Alexander Rose
d993082f24 5.4.0 2025-11-16 10:12:28 -08:00
Alexander Rose
5eaa73d56d changelog 2025-11-16 10:11:07 -08:00
Alexander Rose
b9428fd3cd Merge pull request #1708 from molstar/volume-improvements
Volume improvements
2025-11-16 10:10:11 -08:00
Alexander Rose
97d180b79d use Number.isNaN 2025-11-16 10:07:45 -08:00
Alexander Rose
25bd915ea5 optimize wrapped volume 2025-11-16 10:04:10 -08:00
Alexander Rose
f8fdffdc44 Update src/mol-model-formats/volume/ccp4.ts
Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-11-16 09:45:14 -08:00
David Sehnal
d11aa6ea77 improve guessCifVariant (#1709) 2025-11-16 17:53:16 +01:00
Alexander Rose
fc3c7997ea package updates 2025-11-15 16:54:26 -08:00
Alexander Rose
b3aecf8de4 package updates 2025-11-15 16:46:15 -08:00
Alexander Rose
f3581e62ef schema updates 2025-11-15 16:41:09 -08:00
Alexander Rose
88e7fe508f package updates 2025-11-15 16:32:09 -08:00
Alexander Rose
98049ed02d Merge branch 'master' of https://github.com/molstar/molstar into volume-improvements 2025-11-15 16:25:44 -08:00
Alexander Rose
194092ed67 Merge pull request #1707 from rxht/text-input-chinese-support
Add Chinese language support to the text input box.
2025-11-15 16:23:21 -08:00
Alexander Rose
e96157c890 changelog 2025-11-15 16:19:40 -08:00
Alexander Rose
a028c1ef42 Merge branch 'master' of https://github.com/molstar/molstar into pr/rxht/1707 2025-11-15 16:16:32 -08:00
Alexander Rose
ad2b5e687d Volume improvements
- Add `Volume.periodicity`
- Wrap isosurfaces for periodic volumes
- Fix dimensions for slices
2025-11-15 16:09:47 -08:00
Alexander Rose
8ba19f0be4 Merge pull request #1701 from midlik/bounding-spheres
Bounding spheres include element radius
2025-11-15 09:29:55 -08:00
Alexander Rose
bccc68f6df Merge branch 'master' of https://github.com/molstar/molstar into pr/midlik/1701 2025-11-15 09:06:55 -08:00
Alexander Rose
026a05d03d formating 2025-11-15 09:06:46 -08:00
Alexander Rose
2b4741c8ee Use PluginCommands to set canvas3d props in camera behavior 2025-11-15 08:52:25 -08:00
Alexander Rose
7960ee06d4 Fix default trackball animated spin speed 2025-11-15 08:50:24 -08:00
Alexander Rose
f73f5af131 Fix direct-volume not drawn in illumination mode 2025-11-15 08:48:22 -08:00
rxht
3123110aa4 Add Chinese language support to the text input box. 2025-11-14 10:56:15 +08:00
midlik
154063638d MVS: Allow canvas background interpolation (#1704) 2025-11-13 12:02:10 +01:00
midlik
a720b98365 MVS transformed primitives (#1705)
* MVS: Fix primitives in root not being transformed with reference structure

* MultilayerColorTheme only preferSmoothing when a nested theme prefers

* MVSAnnotationColorTheme do not prefer smoothing

* Update file header
2025-11-11 16:47:35 +01:00
Adam Midlik
d4a2937e0b Merge branch 'master' into bounding-spheres 2025-11-11 15:39:20 +00:00
midlik
b0ca7ffbb7 Fix all-selector color not applying on substructure (#1700)
* Fix all-selector color not applying on substructure

* Fix CHANGELOG

* Size uniform computed from the first included location
2025-11-11 10:32:01 +01:00
David Sehnal
c42b738abe MVS: Fix appendSnapshots when loading MVSX (#1702) 2025-11-11 10:31:06 +01:00
Alexander Rose
ab0d0fec53 Merge pull request #1697 from midlik/label-boundary
Fix bounding sphere computation for 3D text
2025-11-09 17:49:50 -08:00
Alexander Rose
8d96131962 changelog 2025-11-09 17:49:27 -08:00
Alexander Rose
95bbcd8b24 Merge branch 'master' of https://github.com/molstar/molstar into pr/midlik/1697 2025-11-09 17:49:06 -08:00
Alexander Rose
a21f5c2c23 Add viewport button to toggle illumination mode 2025-11-09 16:45:26 -08:00
Adam Midlik
94b7b1281c Merge branch 'master' into bounding-spheres 2025-11-07 10:19:00 +00:00
Adam Midlik
16dba586df Relax camera limits to allow focusing any selection with >1 atom 2025-11-07 10:13:39 +00:00
midlik
72b761f959 Fix ugly camera clipping in snapshot transitions (#1699)
* Fix ugly camera clipping in snapshot transitions

* Update CHANGELOG.md

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-11-06 16:04:20 +01:00
Adam Midlik
943d81cbf9 Fix bounding sphere computation for 3D text 2025-11-06 09:28:09 +00:00
dsehnal
2ecdc0eafa 5.3.0 2025-11-05 14:41:21 +01:00
dsehnal
dccfd35c7a changelog 2025-11-05 14:39:06 +01:00
Dominik Andrew Tichy
9e81a4f7a6 fix: validation and default params for primitives_from_uri (#1690)
* fix: primitives default param values

* chore: changelog

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-11-05 14:37:00 +01:00
midlik
6f6cc73ce9 MVS: tweak param type definitions to make type bundle smaller (#1692)
* MVS: tweak param type definitions to make type bundle smaller

* MVS: add docstring to all parameter definitions

* MVS: tweak param type definitions to make type bundle smaller 2 (palettes)

* add types
2025-11-05 14:21:54 +01:00
David Sehnal
c248ae11bf fix wheel scrolling edge case (#1696) 2025-11-05 13:27:14 +01:00
dsehnal
742be03901 add index file to mvs extension 2025-11-05 09:54:26 +01:00
midlik
00009ef198 MVS: coarse annotations bugfix (#1695) 2025-11-04 23:16:24 +01:00
David Sehnal
1cb617524d MVS: Fix coarse structure selection (#1694) 2025-11-04 23:07:47 +01:00
David Sehnal
e2e348240b MVS: topology format support (#1691)
* MVS: topology format support

* bugfix

* mvs: additional coordinate formats

* fix
2025-11-04 22:16:49 +01:00
Alexander Rose
b54908492c Add Canvas3D.setAttribs 2025-11-03 23:52:26 -08:00
dsehnal
33172862bd mvs stories loading message 2025-11-02 14:07:52 +01:00
dsehnal
c5f2767efc 5.2.0 2025-10-31 17:26:52 +01:00
dsehnal
66f5a81a5d changelog 2025-10-31 17:25:24 +01:00
David Sehnal
9e90e11bfc MVS Improvements (#1684)
* MVS primitives clipping

* camera near distance
2025-10-31 16:43:59 +01:00
midlik
ab372a89d6 MVS: fix persisting tooltips and other fixes (#1688)
* MVS: Fix tooltips persisting across snapshots

* MVS: Fix CIF annotations with no selector columns being ignored

* Vec3.orthogonalize handle special cases (fixes trackpad lock in MVS)

* Update CHANGELOG
2025-10-31 14:35:56 +01:00
Adam Midlik
ea612c3acb Unit and loci bounding sphere includes VDW or coarse sphere radius 2025-10-31 12:50:51 +00:00
Adam Midlik
a1308645e5 Vec3.orthogonalize handle special cases (fixes trackpad lock in MVS) 2025-10-29 14:04:18 +00:00
David Sehnal
c6506d515f Fix CIF Parser edge case (#1687)
* Fix CIF Parser edge case

* header
2025-10-28 15:02:35 +01:00
Adam Midlik
794b705184 MVS: Fix CIF annotations with no selector columns being ignored 2025-10-28 11:56:40 +00:00
Adam Midlik
66264abe50 MVS: Fix tooltips persisting across snapshots 2025-10-28 11:25:29 +00:00
Alexander Rose
7d0f84ff72 Merge pull request #1679 from giagitom/fix-screenshot-helper-change-transparency
Handle transparency mode updates on ImagePass
2025-10-25 14:24:13 -07:00
Alexander Rose
31495ab02a simplify 2025-10-25 14:20:30 -07:00
Alexander Rose
853ad5c916 pass transparency via scene 2025-10-25 14:15:40 -07:00
Alexander Rose
51fc525215 Merge https://github.com/molstar/molstar into pr/giagitom/1679 2025-10-25 13:53:34 -07:00
dsehnal
92d1c446d4 5.1.2 2025-10-25 15:04:28 +02:00
dsehnal
f2a0ff448b mvs custom coloring fix 2025-10-25 15:03:16 +02:00
dsehnal
0ec096a980 5.1.1 2025-10-25 14:30:39 +02:00
dsehnal
44a5b83c1c fix State reconciliation with resolved refs 2025-10-25 14:29:20 +02:00
dsehnal
46c5184d40 5.1.0 2025-10-25 12:35:20 +02:00
dsehnal
7c46306929 5.1 changelog 2025-10-25 12:34:05 +02:00
Gianluca Tomasello
d7fe32d000 Fix createColorScaleByType when offsets are available (#1668)
* Fix createColorScaleByType when offsets are available

* lint-fix

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-10-25 12:31:39 +02:00
David Sehnal
d7beb288c3 Fullscreen mode improvements (#1683)
* Fullscreen mode improvements

* iterate on functionality

* fix imports
2025-10-25 12:29:37 +02:00
Lukas Polak
fb5da1b4d0 ExpandToFullscreen option in PluginConfig (#1666)
* Add PluginConfig.General.ExpandToFullscreen

* Simplify layout.ts

* Update CHANGELOG
2025-10-25 10:25:14 +02:00
David Sehnal
d89e254555 Custom ref resolvers in State (#1682) 2025-10-25 10:12:17 +02:00
midlik
99e11317e1 MVS: residue_index selector (#1681)
* MVS builder - add sphere and angle

* MVS: Annotations for coarse models

* MVS: Rename AtomRanges -> ElementRanges

* MVS: refactor

* MVS: Labels for coarse structures

* fix tests

* MVS: refactor IndicesAndSortings

* MVS: refactor IndicesAndSortings 2

* MVS: builder method primitives_from_uri -> primitivesFromUri

* Update CHANGELOG

* Add AtomicHierarchy.residueSourceIndex

* MVS: implement residue_index selector for annotations

* MVS: residue_index for inline selectors
2025-10-25 10:10:06 +02:00
David Sehnal
3dc6c4452d [wip] carb constants updates (#1680)
* [wip] carb constants updates

* GlycamSaccharideNames
2025-10-24 19:29:56 +02:00
midlik
3a627a878b MVS - annotations for coarse structures, tidy up builder (#1672)
* MVS builder - add sphere and angle

* MVS: Annotations for coarse models

* MVS: Rename AtomRanges -> ElementRanges

* MVS: refactor

* MVS: Labels for coarse structures

* fix tests

* MVS: refactor IndicesAndSortings

* MVS: refactor IndicesAndSortings 2

* MVS: builder method primitives_from_uri -> primitivesFromUri

* Update CHANGELOG
2025-10-24 15:47:14 +02:00
giagitom
6f9fed180d update headers 2025-10-21 21:56:37 +02:00
giagitom
5ecd176f20 Handle transparency mode updates on ImagePass 2025-10-21 21:50:42 +02:00
David Sehnal
dff3837df6 MVS tweaks (#1678) 2025-10-21 12:15:43 +02:00
Alexander Rose
e42eb31b73 Merge pull request #1675 from molstar/ar-magic-window
Support "magic window" style AR
2025-10-19 16:34:48 -07:00
Alexander Rose
721c117309 handle viewport size 2025-10-19 16:32:06 -07:00
Alexander Rose
216715b2d5 Support "magic window" style AR 2025-10-18 15:33:11 -07:00
Alexander Rose
412d4d5bcd fix clip objects for deirect-volume rendering 2025-10-18 15:27:53 -07:00
falko-apheris
2734d5754a Update example to use mol* v5 (#1673)
Rename initViewer to initViewerAsync in documentation
2025-10-16 19:14:12 +02:00
Alexander Rose
c10f9d8c78 Merge pull request #1667 from giagitom/fix-flipped-normals
fix for flipped surface normal issue
2025-10-11 16:31:45 -07:00
Alexander Rose
7140135cbe changelog 2025-10-11 16:31:05 -07:00
Alexander Rose
b5969945b4 Merge branch 'master' of https://github.com/molstar/molstar into pr/giagitom/1667 2025-10-11 16:30:22 -07:00
Alexander Rose
7f5b3bc16c remove extra variable 2025-10-11 16:28:30 -07:00
Alexander Rose
5cf7b6624b Merge pull request #1669 from papillot/pdb-conect-to-bond-order
Get bonds orders from CONECT records
2025-10-11 16:20:24 -07:00
Alexander Rose
56225b337d header 2025-10-11 16:19:51 -07:00
Paul Pillot
79b6ad6f48 Get bonds orders from CONECT records 2025-10-09 22:09:57 -04:00
giagitom
d0df53dd02 fix for flipped normal issue 2025-10-03 19:36:05 +02:00
Alexander Rose
3b97bfd9b6 5.0.0 2025-09-28 10:41:25 -07:00
Alexander Rose
9b12623131 changelog 2025-09-28 10:39:51 -07:00
Alexander Rose
425370d63e package updates 2025-09-28 10:36:37 -07:00
Alexander Rose
1666c89222 doc tweak 2025-09-28 10:30:28 -07:00
Alexander Rose
a7dd4fc555 change viewer.show-xr to allow 'auto' | 'always' | 'never' 2025-09-28 10:25:48 -07:00
Alexander Rose
9f1760fbf2 pointer: end gesture only if all button are released 2025-09-28 09:54:10 -07:00
Alexander Rose
d7fb040b77 fix shader-manager update 2025-09-21 15:40:27 -07:00
Alexander Rose
2d7c1bcea2 Merge pull request #1665 from molstar/global-defines
global defines
2025-09-21 15:27:22 -07:00
Alexander Rose
a08c434f35 add missing schema 2025-09-21 09:34:42 -07:00
Alexander Rose
45d402bb9f global defines 2025-09-20 21:08:46 -07:00
Alexander Rose
4556544043 package updates 2025-09-20 14:55:58 -07:00
Alexander Rose
921d700761 remove unused dep 2025-09-20 14:52:11 -07:00
Alexander Rose
9605783f41 defer readPixels call in texture-mesh position-iterator 2025-09-20 14:51:23 -07:00
Alexander Rose
f23329dc68 improve resource byte count logging 2025-09-20 14:48:50 -07:00
Alexander Rose
5f4ac6b2c0 remove unused properties 2025-09-20 14:36:39 -07:00
David Sehnal
f0c2961e95 use esbuild jest transformer (#1662) 2025-09-16 20:28:34 +02:00
David Sehnal
2bdaa565b4 Fix screenshot animation loop handling (#1660) 2025-09-16 20:09:33 +02:00
Jose Manuel Duarte
ab2bcde794 Add robots.txt to ModelServer (#1659) 2025-09-16 08:05:30 +02:00
Alexander Rose
0b9674e14c Merge pull request #1655 from molstar/parallel-shader-compile
Adaptive parallel shader compilation
2025-09-15 21:32:52 -07:00
Alexander Rose
07cbeb524e Merge pull request #1653 from giagitom/fix-illum-denoise
Fix illumination denoising with transparency on transparent background
2025-09-15 21:31:31 -07:00
Alexander Rose
8ff75ea2ab Merge branch 'master' into fix-illum-denoise 2025-09-15 21:31:10 -07:00
Alexander Rose
6f5db94b2f add shader-manager
- ensure required shaders for image pass
- take scene content into account
2025-09-15 21:30:12 -07:00
dsehnal
2637957141 pass isSynchronous to finalizePrograms 2025-09-15 08:59:49 +02:00
Alexander Rose
c1bb6f3987 changelog 2025-09-14 21:50:47 -07:00
Alexander Rose
d8df904951 Merge branch 'master' of https://github.com/molstar/molstar into parallel-shader-compile 2025-09-14 21:43:07 -07:00
Alexander Rose
a7ca7c922d adaptive parallel shader compile
- split shader compilation into linking and finalizing
- avoid compiling un-needed shaders
2025-09-14 21:38:27 -07:00
Alexander Rose
f257992a5a Revert "add "ready" commit queue"
This reverts commit bdd1805620.
2025-09-14 21:23:52 -07:00
김주호
62f9f6077d Update to_mmCIF function to accept multiple structures (#1658)
* update to_mmCIF function to accept multiple structures

* update changelog and code header
2025-09-12 09:51:11 +02:00
midlik
e4edb67f62 export class Layout extends PluginUIComponent (#1657) 2025-09-10 14:05:50 +02:00
dsehnal
185ccf5ca6 tweak story title 2025-09-09 11:34:09 +02:00
dsehnal
bdd1805620 add "ready" commit queue 2025-09-09 11:01:13 +02:00
Alexander Rose
29f2722851 wip 2025-09-09 00:07:07 -07:00
giagitom
b38f8b08da Fix illumination denoising with transparency on transparent background 2025-09-08 13:23:34 +02:00
Alexander Rose
6d02889f84 type fixes 2025-09-07 22:25:32 -07:00
Alexander Rose
b864634f1d spec fixes 2025-09-07 19:36:33 -07:00
Alexander Rose
248662b95c update workflow 2025-09-07 19:31:43 -07:00
Alexander Rose
0eb28bd89e schema updates 2025-09-07 18:41:12 -07:00
Alexander Rose
e466bf9ba9 package updates 2025-09-07 18:38:29 -07:00
Alexander Rose
a14c4faefd Merge pull request #1639 from giagitom/fix-transparency-check
Outlines improvements
2025-09-07 16:56:54 -07:00
Alexander Rose
b87a7f069e Merge branch 'master' into fix-transparency-check 2025-09-07 16:56:45 -07:00
Alexander Rose
674a56e2f3 Merge pull request #1590 from molstar/webxr
WebXR
2025-09-07 16:55:56 -07:00
Alexander Rose
521d8cb4f8 Merge branch 'master' of https://github.com/molstar/molstar into webxr 2025-09-07 16:53:14 -07:00
Alexander Rose
bd1d85e927 Merge pull request #1651 from molstar/picking-too-many-groups
improve picking of objects with many groups
2025-09-07 16:49:02 -07:00
Alexander Rose
4d62b928f8 improve picking of objects with many groups
- if to many groups (currently >=2^24-2) pick whole instance/object
2025-09-06 14:05:22 -07:00
Jose Manuel Duarte
014c9607d9 Use new validation/view endpoint at files.rcsb.org (#1649)
* Use new validation/view endpoint at files.rcsb.org

* Update changelog
2025-09-06 11:56:03 +02:00
midlik
98ef24fc9e Sequence color 2 (#1644)
* Sequence color extension - allow props to be provided

* typing fix
2025-09-04 19:49:20 +02:00
dsehnal
c04580377b 5.0.0-dev.13 2025-09-03 09:20:26 +02:00
David Sehnal
a492b38368 fix mutative use & assign NODE_ENV=production for prd builds (#1642)
* fix mutative use & assign NODE_ENV=production for prd builds

* fix type
2025-09-03 09:07:23 +02:00
midlik
518f21531e SequenceColor extension (#1611)
* MinimizeRmsd.Result include nAlignedElements

* SequenceColor extension

* SequenceColor extension - forceUpdate when custom prop changes

* SequenceColor extension - proper caching

* Update CHANGELOG

* SequenceColor extension - registry

* SequenceColor extension - refactor

* SequenceColor extension - minor changes

* SequenceColor extension - switch to experimentalSequenceColorTheme

* SequenceColor extension - ensureCustomProperties

* SequenceColor extension - clean

* SequenceColor extension - avoid repeated allocation for Location

* SequenceColor extension - memoizeLatest, but wrong

* SequenceColor extension - memoizeLatest fixed

* SequenceColor extension - remove unnecessary loci caching

* SequenceColor extension - clean up
2025-09-03 07:29:40 +02:00
David Sehnal
36fd40ee09 VolumeServer: Default to P1 spacegroup (#1640)
* CCP4 parser defaultToP1 option

* volume server: default to P1

* tweaks

* tweak
2025-09-02 17:47:58 +02:00
giagitom
6b8c604762 improvements 2025-09-02 17:28:16 +02:00
giagitom
c10382d1fb Handle illumination 2025-09-02 15:23:50 +02:00
Alexander Rose
0e968ae59c Fix ColorScale for continuous case without offsets 2025-09-01 16:09:12 -07:00
giagitom
1286a9e560 Fix tests 2025-09-01 22:10:49 +02:00
giagitom
bf73712781 Add packing/unpacking functions 2025-09-01 22:03:36 +02:00
giagitom
53922db113 Outlines improvements 2025-09-01 17:56:03 +02:00
giagitom
799037d657 Merge branch 'master' of https://github.com/molstar/molstar into fix-transparency-check 2025-09-01 17:52:15 +02:00
Alexander Rose
5cb7a3cc8e pixel-based size of pointer helper points 2025-08-31 18:33:46 -07:00
Alexander Rose
c14cbb258d fix size calculation and update of text geometry 2025-08-31 18:33:07 -07:00
Alexander Rose
8a860497f1 support ray-picking of text geometry
- uses extra eye camera in text shader
2025-08-31 18:32:38 -07:00
Alexander Rose
77d4d0007c Merge branch 'master' of https://github.com/molstar/molstar into webxr 2025-08-31 17:45:45 -07:00
dsehnal
005824eb24 5.0.0-dev.12 2025-08-31 10:08:11 +02:00
dsehnal
259e04a6ce move mvs validation to a separate file 2025-08-31 10:06:20 +02:00
dsehnal
966bc14c67 5.0.0-dev.11 2025-08-31 09:51:54 +02:00
David Sehnal
f752b7e155 MVS: Color map interpolation & canvas backgrounds (#1636)
* MVS: Color map interpolation

* print validation errors to plugin log

* fixes

* background postprocessing

* fix resetCanvasProps

* fix link

* add example
2025-08-31 09:36:50 +02:00
Gianluca Tomasello
255b8b9ac3 Fix renderer transparency check (#1635)
* Fix renderer transparency check

* Fading transparent outlines

* improvements
2025-08-29 17:59:26 +02:00
giagitom
15c4fb3c01 improvements 2025-08-29 15:01:31 +02:00
giagitom
9fba0c08b2 Fading transparent outlines 2025-08-28 21:26:06 +02:00
giagitom
f08dd0255d Fix renderer transparency check 2025-08-28 11:44:05 +02:00
Victoria Doshchenko
42d969bbeb MVS: example story improvements (#1632)
* add intro scene

* fixes

* add author name
2025-08-26 18:55:34 +02:00
dsehnal
fdc33e44dc 5.0.0-dev.10 2025-08-26 17:43:06 +02:00
David Sehnal
b0aa889a0a MVS: Animation improvements (#1631)
* allow interpolation "keyframing"

* animation fixes
2025-08-26 17:41:21 +02:00
David Sehnal
4d7bd53231 Additional markdown commands (#1630) 2025-08-26 06:58:40 +02:00
David Sehnal
c11cf665c9 Additional markdown extensions (#1629)
* additional markdown extensions

* fixes
2025-08-25 20:12:10 +02:00
dsehnal
a4b09d3a0c 5.0.0-dev.9 2025-08-25 17:00:54 +02:00
David Sehnal
6e488b0f80 MotM1 Story tweaks (#1627)
* tweak story

* bugfixes & tweaks

* linting

* support "discrete" scalar transform

* tweak audio path

* tweak ui
2025-08-25 08:22:36 +02:00
Alexander Rose
2cef723483 naming fix 2025-08-24 22:46:41 -07:00
ludovic autin
6164281a50 initial work on MOM number 1 with audio comments (#1624)
* initial work on MOM number 1 with audio comments

* add some TODO comments

* separate audio as mp3. Do coloring with DG scheme

* move audio in root example folder. test some query in mol-script

* salt bridge.

* better coloring

* support for entry-id test in MolScriptBuilder.

* lint

* update audio, sync animation

* cleanup

* clean up and sync audio/anim

* add reference to MOM1
2025-08-25 07:14:46 +02:00
Alexander Rose
c74a014ab7 update package.lock for ci 2025-08-24 14:54:27 -07:00
Alexander Rose
4bbf1dc8aa refactor xr input handling 2025-08-24 14:52:58 -07:00
Alexander Rose
6e53621e01 Merge branch 'master' of https://github.com/molstar/molstar into webxr 2025-08-24 13:42:49 -07:00
Alexander Rose
2db7171e2a Merge pull request #1625 from molstar/trackball-state-tweaks
Trackball & Snapshot handling tweaks
2025-08-24 13:42:24 -07:00
Alexander Rose
edfc094952 re-add the !isBusy check
Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-08-24 13:35:37 -07:00
David Sehnal
b3e1e2900b Fix Markdown Commands query focus (#1626) 2025-08-24 13:18:36 +02:00
Alexander Rose
ba2bc206cc Merge branch 'master' of https://github.com/molstar/molstar into webxr 2025-08-23 14:59:17 -07:00
Alexander Rose
1e498d535a add SnapshotControls behavior 2025-08-23 10:44:50 -07:00
Alexander Rose
6ed969cd1b don't save behaviors in me snapshots 2025-08-23 10:42:05 -07:00
Alexander Rose
27bb4f4bca remove unused trackball param 2025-08-23 10:41:21 -07:00
Alexander Rose
6ce2139272 add canvas3d/trackball attribs
- attribs are configurable but are not saved in the state like props
2025-08-23 10:41:04 -07:00
Alexander Rose
856eff5127 ensure xr props are set each frame, make passthrough default 2025-08-23 10:19:50 -07:00
dsehnal
13cf6613a6 fix typo 2025-08-23 19:18:21 +02:00
Alexander Rose
52b141c4fa fix pointer-helper camera 2025-08-23 10:15:39 -07:00
Alexander Rose
701844ca7c remove unused uniform 2025-08-23 10:14:49 -07:00
Alexander Rose
bcc572bd18 move scale, minTargetDistance, forceFull to camera properties 2025-08-23 10:14:29 -07:00
David Sehnal
c5bb13e295 Execute markdown commands on snapshot load (#1622) 2025-08-22 18:25:24 +02:00
dsehnal
34c8257848 5.0.0-dev.8 2025-08-22 16:05:31 +02:00
David Sehnal
fcbf39c935 Markdown & MVS: Audio support (#1621)
* audio playback markdown commands

* trigger markdown commands from MVS primitives

* docs

* fix usage of mutative
2025-08-22 16:00:30 +02:00
dsehnal
46c8150b2b 5.0.0-dev.7 2025-08-21 14:05:04 +02:00
David Sehnal
af1a864daa replace immer with mutative, optimize MVS animation loading (#1618) 2025-08-21 14:03:22 +02:00
David Sehnal
3babd9399a MVS: Add backbone and line representation types (#1617) 2025-08-20 17:33:03 +02:00
David Sehnal
e57564486f mol-state: fix param normalization (#1616)
* mol-state: fix param normalization

* headers
2025-08-19 19:33:01 +02:00
midlik
464a91ac29 Add PluginConfig.Viewport.ShowReset (#1615)
* Add PluginConfig.Viewport.ShowReset

* Update CHANGELOG
2025-08-18 12:02:31 +02:00
Alexander Rose
4b58ce94ee Merge branch 'master' of https://github.com/molstar/molstar into webxr 2025-08-17 23:43:19 -07:00
Alexander Rose
16b0374eac tweak trackball forward/backward movement behavior 2025-08-16 16:10:54 -07:00
Alexander Rose
67e63dccb4 improve/fix sphere rendering for asymmetric projections 2025-08-16 14:42:03 -07:00
Alexander Rose
2cc600cc52 add xr.sceneRadiusInMeters param
- tweak mesoscale explorer xr defaults
2025-08-16 14:40:43 -07:00
Alexander Rose
27fa50a5de Merge pull request #1610 from giagitom/dpoit-monolayer-transparency
Add Monolayer transparency (exploiting dpoit)
2025-08-16 14:37:34 -07:00
David Sehnal
1e323f18f7 MVS: additional formats and trajectory support (#1613)
* MVS: additional formats and trajectory support

* refactoring

* support lammpstrj

* tweaks

* remove test code
2025-08-15 20:10:13 +02:00
midlik
2685b2b77d MVSX use Murmur hash (#1612) 2025-08-15 14:11:53 +02:00
David Sehnal
d71b47a515 MVS Stories and related updates (#1609)
* mvs-stories updates, better snapshot playback if transition is present

* Add createMVSX

* mvs: support trackball animation

* tweak

* more fine grained speed of camera spin animation

* update TrackballControlsParams.animate.spin.speed

* story-session-url arg support
2025-08-15 13:27:34 +02:00
giagitom
88cc720dd2 fix render without postprocessing 2025-08-14 23:34:45 +02:00
giagitom
201433cc91 Lint fix 2025-08-14 19:53:36 +02:00
giagitom
8582303491 Add Monolayer transparency (exploiting dpoit) 2025-08-14 19:40:24 +02:00
dsehnal
655c3edadd 5.0.0-dev.6 2025-08-14 11:37:40 +02:00
David Sehnal
a4323a4bd8 MVS animation improvements (#1608) 2025-08-14 11:33:50 +02:00
dsehnal
1b5a7d9546 5.0.0-dev.5 2025-08-13 18:44:02 +02:00
David Sehnal
f165cc4629 MVS: Animations (#1606)
* object hash

* hashed StateTransform.version

* StateTree.reuseTransformParams

* State animation data model

* mvs animation tree schema and builder

* generate animation

* snapshot animation ui

* async animation generation

* ui tweak

* ui tweak

* wrap loadMVS in task

* state snapshots animation

* snapshot transition animation

* autoplay transition

* vector and rotation matrix interpolation

* local rotation transform

* fixes and better demo

* unused import

* tweak

* changelog

* headers

* type => kind

* mat4 interpolation

* use proper time in animation loop

* animated label opacity

* typo

* add postprocessing to demo

* fix mvs postprocessing params

* add transform_matrix interpolation

* tweak

* generalize vector interpolation

* Color.interpolateHcl

* resetCanvasProps

* rename from/to to start/end

* transform def

* add frequency param

* update interpolations

* cache rotation, do not apply noise to last frame

* local_rotation => rotation_center

* changelog

* fix build

* add animation.duration_ms

* PR feedback

* add hsl color space

* default canvas bg

* scalar list interpolation

* color interpolation props
2025-08-13 18:41:56 +02:00
Alexander Rose
cb499ce42e Merge pull request #1607 from corredD/webxr
fix shadow
2025-08-12 22:51:28 -07:00
Alexander Rose
db247d6fbd remove mat4 allocation 2025-08-12 22:49:14 -07:00
Alexander Rose
23701bf8e8 always consider bounds 2025-08-12 22:47:56 -07:00
ludovic autin
2e1f2e7eec fix shadow 2025-08-12 10:58:05 -07:00
Alexander Rose
fdb3ff54f1 fix: apply model-scale to alpha-thickness 2025-08-11 22:19:52 -07:00
Alexander Rose
d5fd56718d tweak shadow pass 2025-08-10 20:52:39 -07:00
Alexander Rose
0698ac6dd5 changelog 2025-08-10 11:55:06 -07:00
Alexander Rose
825b59ab1e fix multi scale ssao update when camera scale changes 2025-08-10 11:21:17 -07:00
Alexander Rose
3086d1a5c8 Merge branch 'master' of https://github.com/molstar/molstar into webxr 2025-08-10 10:47:45 -07:00
Alexander Rose
138796862b Merge pull request #1589 from giagitom/dot-volume-improvements
Dot volume representation improvements
2025-08-10 10:44:39 -07:00
Alexander Rose
1b236f1ae5 cleanup 2025-08-10 10:42:17 -07:00
Alexander Rose
b6c2e25395 cleanup 2025-08-10 10:37:44 -07:00
giagitom
b7816986aa lint-fix 2025-08-10 13:07:54 +02:00
giagitom
437c70a75a Apply suggestions 2025-08-10 13:05:08 +02:00
giagitom
de85e0fbae Add extractBasis helper to mat4 2025-08-10 12:49:09 +02:00
Alexander Rose
8f7fda4919 cleanup 2025-08-09 23:14:48 -07:00
Alexander Rose
470ccd333f improve forward/back movement
- when camera is outside of visible boundingsphere, move a fraction of the distance to the target
2025-08-09 23:00:28 -07:00
Alexander Rose
2b6d067b0e reset xr scale when camera resets in canvas3d 2025-08-09 20:29:31 -07:00
Alexander Rose
0b928888a5 apply standard pixel scale in addition to xr resolution scale 2025-08-09 18:18:37 -07:00
Alexander Rose
28edfd44cb add xr settings to mesoscale explorer ui 2025-08-09 18:17:25 -07:00
Alexander Rose
3391c6de07 add simple culling for scaled scenes 2025-08-09 18:16:55 -07:00
Alexander Rose
12b7951700 better model scale handling for clipping and lods 2025-08-09 18:15:52 -07:00
giagitom
c527b59782 optimization 2025-08-09 21:01:33 +02:00
giagitom
3bbbac66c7 lint fix 2025-08-09 12:36:29 +02:00
giagitom
c0980bf18a Improvements in perturbation obtainment 2025-08-08 23:21:54 +02:00
giagitom
45eab19493 refactor 2025-08-08 16:57:56 +02:00
giagitom
1e2a5a5bfd - Rename property and refactor
- handle  non-orthogonal cell
2025-08-08 16:45:22 +02:00
giagitom
45edfa8014 Merge branch 'master' of https://github.com/molstar/molstar into dot-volume-improvements 2025-08-08 14:38:06 +02:00
David Sehnal
899203c855 MVS: surface_type option (#1603) 2025-08-07 11:15:44 +02:00
김주호
ef823b066b Change PDB parsing to use four-letter residue names (#1602)
* Add is4LetterResidueName option for parsing .pdb

* update metadata for request pullrequest

* Always parse PDB files using four-letter residue names. (#1601) (#1602)

* Write changelog about parsing resname 4-letter

* Update src/mol-plugin-state/formats/trajectory.ts

* Update src/mol-model-formats/structure/pdb/to-cif.ts

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-08-06 07:36:20 +02:00
dsehnal
33dc2015df 5.0.0-dev.4 2025-08-05 09:55:55 +02:00
dsehnal
fcf5ea420b npm audit 2025-08-05 09:54:34 +02:00
dsehnal
8d97327f8d MVS: fix passing custom primitive params 2025-08-05 09:53:58 +02:00
Alexander Rose
cbc0e857fc log entering/exiting xr 2025-08-04 22:20:10 -07:00
Alexander Rose
01ce306405 handle multiple input sources 2025-08-04 22:16:26 -07:00
Alexander Rose
a39a49e884 improve event handling and listen to device change 2025-08-03 23:08:30 -07:00
Alexander Rose
887a39dde9 more cleanup/refactoring and basic error handling 2025-08-03 18:14:31 -07:00
midlik
abc7ebba3e MVS: Fix MVSInlinePrimitiveData param type (#1592) 2025-08-03 17:48:19 +02:00
David Sehnal
73d593907e MVS cavnas molstar_postprocessing (#1598) 2025-08-03 12:04:53 +02:00
Alexander Rose
84a45fabdc cleanup/refactor
- moved button out of canvas3d
- add button to render-structure browser test
- add button to plugin viewport
2025-08-02 18:54:17 -07:00
dsehnal
0dc05e1138 5.0.0-dev.3 2025-08-02 18:21:14 +02:00
David Sehnal
dd11cacae4 Markdown Commands and MVS improvements (#1597)
* add query command to markdown extensions

* fix typo

* better postprocessing param support in MVS

* molstar_mesh/label/line_params
2025-08-02 18:19:01 +02:00
Alexander Rose
ea17902aa6 handle webxr with external "animation" control
- add Canvas3D.request/cancelAnimationFrame
- keep copy of animation callback to automatically resume
2025-08-02 07:23:46 -07:00
David Sehnal
b503259758 another io-ts import fix (#1595) 2025-08-01 06:28:26 +02:00
zachcp
1e98741e16 Update field-schema.ts (#1594) 2025-08-01 05:38:41 +02:00
dsehnal
f879519700 5.0.0-dev.2 2025-07-31 18:31:41 +02:00
zachcp
c6e175e5da Update field-schema.ts (#1593)
Follow on from #1587  to make `JS` explicit.
2025-07-31 18:29:28 +02:00
dsehnal
add75bf9c9 5.0.0-dev.1 2025-07-28 16:37:17 +02:00
dsehnal
57cbcd5fbf npm audit 2025-07-28 16:34:08 +02:00
giagitom
50a820b0ae - Add perturbatePositions property
- Fixes and improvements
2025-07-28 16:10:52 +02:00
zachcp
0a33936e06 Update field-schema.ts to point directly to PathReporter (#1587) 2025-07-28 07:48:00 +02:00
Alexander Rose
2abbb843f8 update lock file 2025-07-27 18:14:15 -07:00
Alexander Rose
32179f31c2 webxr, wip
- add pointer-helper
- add xr-manager to handle xr input and session
- support xr render loop in canvas3d
- add camera.state.minTargetDistance (don't want things too close to your eyes)
- add camera.state.forceFull to show frustum from camera to end of scene
- basic input handling (single controller)
2025-07-27 17:38:53 -07:00
Alexander Rose
7291025e09 Merge pull request #1585 from molstar/scene-scale
Scene scale
2025-07-27 17:18:57 -07:00
giagitom
0cb2c3621b Dot volume representation improvements 2025-07-28 02:07:54 +02:00
Alexander Rose
86da258280 Merge branch 'master' of https://github.com/molstar/molstar into scene-scale 2025-07-26 17:42:54 -07:00
Alexander Rose
477a80d1ca fix post-processing params hideIf logic 2025-07-26 17:40:14 -07:00
Alexander Rose
86b68018a9 add scene scaling support 2025-07-26 17:39:44 -07:00
Alexander Rose
da095d6ef9 handling move/dragt before resolving pickData breaks ray-picking 2025-07-26 16:46:08 -07:00
Alexander Rose
dc304b9e08 Merge pull request #1583 from molstar/fix-async-buffer
fix async buffer issues
2025-07-26 16:22:43 -07:00
Alexander Rose
c905fa17c4 tweak 2025-07-26 16:22:33 -07:00
Alexander Rose
a06c64e8e0 Merge pull request #1584 from molstar/pp-switch
add `enable` param for post-processing effects
2025-07-26 16:05:25 -07:00
Alexander Rose
f5441290dd Merge pull request #1567 from giagitom/box3d-spec
add tests for box3D nearestIntersectionWithRay3D
2025-07-26 16:04:59 -07:00
Alexander Rose
9f23124317 move ray box intersection code to Ray3D 2025-07-26 15:59:40 -07:00
dsehnal
8299cd638c tweaks 2025-07-26 20:37:42 +02:00
Alexander Rose
50cb08e74d Merge branch 'master' of https://github.com/molstar/molstar into fix-async-buffer 2025-07-26 07:55:21 -07:00
Alexander Rose
89552652ba Merge branch 'master' of https://github.com/molstar/molstar into pp-switch 2025-07-26 07:55:02 -07:00
Alexander Rose
37ce577813 fix text shader 2025-07-26 07:54:28 -07:00
Alexander Rose
4d9a003141 add enable param for post-processing effects
- If false, no effects are applied.
2025-07-26 07:45:59 -07:00
Alexander Rose
6f0311a53f fix async buffer issues
- mark pick-helper dirty when async pick failed
- add pixel-pack buffer wrapper
- recover pixel-pack buffer after context loss (pick buffer, hi-z pass)
2025-07-26 07:30:54 -07:00
Alexander Rose
bfd2d6b055 text shader: head rotation tweak 2025-07-26 07:23:49 -07:00
Alexander Rose
3072e60709 Merge pull request #1582 from molstar/revert-1581-fix-async-identify
Revert "fix async identify"
2025-07-26 07:22:33 -07:00
Alexander Rose
62ed8d10e3 Revert "fix async identify (#1581)"
This reverts commit 13d3c34864.
2025-07-26 07:22:12 -07:00
David Sehnal
13d3c34864 fix async identify (#1581) 2025-07-25 18:42:29 +02:00
David Sehnal
cac433efca MVS Stories: Add "Download MVS State" link (#1580) 2025-07-25 14:31:07 +02:00
dsehnal
b25ffe7151 Canvas3dInteractionHelper fix 2025-07-25 10:53:02 +02:00
David Sehnal
31074dc74c fix inv het rotation uniform (#1578) 2025-07-25 10:34:13 +02:00
giagitom
c98c01a076 fix names 2025-07-23 18:24:56 +02:00
giagitom
8966fc9396 refactor 2025-07-23 18:23:12 +02:00
dsehnal
fdbdc551e8 fix web component syntax 2025-07-22 15:25:44 +02:00
dsehnal
bb232ac3a4 pass format in mvs stories app 2025-07-22 14:37:51 +02:00
giagitom
735c25ef8d Merge branch 'master' of https://github.com/molstar/molstar into box3d-spec 2025-07-22 14:13:07 +02:00
Alexander Rose
298043313a head rotation handling tweaks 2025-07-20 22:07:37 -07:00
Alexander Rose
77cd181b91 add addCylinderFromRay3D helper function 2025-07-20 09:02:31 -07:00
Alexander Rose
b5bee042e8 add groupCount argument to Shape.create 2025-07-20 08:48:43 -07:00
Alexander Rose
4faf17ddc7 Merge pull request #1576 from molstar/headrotation
Add head rotation support
2025-07-20 08:45:15 -07:00
Alexander Rose
28774b2277 fix scale issues in cylinders & spheres shaders 2025-07-19 16:13:48 -07:00
Alexander Rose
6a7444f44e add head rotation support
- handle skybox
- handle sphere & text billboards
2025-07-19 16:13:00 -07:00
Alexander Rose
15bfa8416a Merge pull request #1575 from molstar/async-ray-picking
add async & ray picking
2025-07-19 15:16:01 -07:00
Alexander Rose
e6895ec833 cleanup, simplify AsyncPickData 2025-07-19 15:08:46 -07:00
Alexander Rose
2099ad728a add async & ray picking 2025-07-19 09:13:49 -07:00
dsehnal
72ae3fae65 5.0.0-dev.0 2025-07-19 09:30:04 +02:00
dsehnal
bb5ad78681 eslint fix 2025-07-19 09:28:44 +02:00
dsehnal
f10e88612f npm audit 2025-07-19 09:26:55 +02:00
David Sehnal
a2e582d4a9 update MVS Stories app and deploy scripts (#1574)
* update MVS Stories app and deploy scripts

* reorder changelog
2025-07-19 09:25:32 +02:00
David Sehnal
572874f4ae Rename SymmetryOperator.canonicalName to instanceId (#1571) 2025-07-19 07:46:43 +02:00
David Sehnal
b9c0347497 MVS: grid-slice volume representation, label improvements, state transitions via 3D interactions, instacing (#1570)
* MVS: grid-slice volume representation

* tweak

* type fix

* label tether support

* snapshot_key support

* custom MVSShapeRepresentation3D

* renaming

* structure and volume instancing

* fix mixin
2025-07-19 07:46:01 +02:00
midlik
089148198f MVS operator_name (#1561)
* Change symmetry operator naming

* MVS operator_name selector for inline component, color, label, tooltip

* MVS operator_name selector in annotations (component/color/label/tooltip_from_uri/source)

* Revert changes to operatorName, add canonicalOperatorName instead, rename MVS selector field operator_name -> instance_id

* Update CHANGELOG

* Remove polyfill.io in mkdocs

* MVS: MultilayerColorThemeName decide granularity smartly

* MVS: MultilayerColorThemeName refactor
2025-07-11 20:45:22 +02:00
giagitom
6fc04c3294 add tests for box3D nearestIntersectionWithRay3D 2025-07-07 18:46:06 +02:00
Alexander Rose
dc55577e22 chanelog 2025-07-06 15:28:43 -07:00
Alexander Rose
f7ba7c0511 add Ray3D and math fixes/improvements 2025-07-06 15:24:47 -07:00
Alexander Rose
ed5374fab9 improve volume visual group count update 2025-07-06 10:10:02 -07:00
Alexander Rose
9a04b4f0df instanced volume (#1557)
* wip, instanced volume

* add Orderset.isEmpty and Interval.offset

* add Box3D.addBox3D

* support volume instances

- add Volume.instances
- add Volume.InstanceIndex and Volume.SegmentIndex types
- volume loci improvements

* add volume-instance color theme

* add VolumeInstances xform

* breaking note

* trailing space

* remove setting that breaks ESlint in VSCode

* tweak angle param

* reuse volume visuals when only instance transforms change

* tweaks

---------

Co-authored-by: dsehnal <david.sehnal@gmail.com>
2025-07-06 19:04:03 +02:00
Alexander Rose
9350e539b6 Merge pull request #1566 from molstar/fix-group-count
Fix group count calculation on geometry update
2025-07-06 09:48:20 -07:00
Alexander Rose
c38377af46 Merge pull request #1564 from molstar/mol2-improvements
Mol2 Reader improvements
2025-07-05 16:57:00 -07:00
Alexander Rose
9804febd95 Merge branch 'master' into mol2-improvements 2025-07-05 16:56:51 -07:00
Alexander Rose
7936dc1840 Fix wrong instance index in calcMeshColorSmoothing 2025-07-05 15:53:08 -07:00
Alexander Rose
a033a8be36 Fix group count calculation on geometry update 2025-07-04 23:24:39 -07:00
Alexander Rose
4b84c6dcba fix typo MarchinCubes -> MarchingCubes 2025-07-04 23:22:38 -07:00
Alexander Rose
309d792fdb fix shader error when clipping flags are set without clip objects present 2025-07-04 17:51:59 -07:00
Alexander Rose
c437254680 add substructure spec 2025-07-04 16:15:55 -07:00
Alexander Rose
6fbf7c7a22 fix spec 2025-07-04 16:01:55 -07:00
Alexander Rose
86a7520b90 Mol2 Reader improvements
- Fix column count parsing
- Add support for substructure
2025-07-04 15:11:43 -07:00
David Sehnal
cd10043447 MVS: clip node support (#1553)
* MVS: clip node support

* rename transform to point_transform

* fix vec3/mat4 control overflow

* refactor mvs clipping

* unused var

* tweaks
2025-07-04 18:03:37 +02:00
David Sehnal
146e95cb23 Snapshot Markdown Improvements (#1555)
* basic markdown commands

* markdown renderers

* support markdown tables

* fix style

* indicate external links in markdown

* simplify the api

* load image from MVSX

* lint

* docs

* typo

* custom color palette support

* move manager to mol-plugin-state

* customize args parser

* better custom args parser support
2025-07-04 10:29:03 +02:00
David Sehnal
13b1e5d59c Async Viewer Init (#1394)
* async viewer init

* changelog

* tweak changelog

* make context init functions async
2025-07-01 09:52:45 +02:00
Alexander Rose
ae3efa53d6 Merge pull request #1556 from molstar/coarsegrained-unit-trait
Avoid calculating rings for coarse-grained structures
2025-06-29 22:16:32 -07:00
Alexander Rose
2e67fbe870 Merge branch 'master' into coarsegrained-unit-trait 2025-06-29 22:16:20 -07:00
dsehnal
56df6f82a7 docs tweak 2025-06-29 21:16:34 +02:00
Alexander Rose
fdd874b7a6 Merge pull request #1554 from giagitom/isosurface-fix
Fix isosurface compute shader normals when transformation matrix is applied to volume
2025-06-28 17:22:38 -07:00
Alexander Rose
f142c3ef1b lint 2025-06-28 17:20:04 -07:00
Alexander Rose
978b53e7d8 Avoid calculating rings for coarse-grained structures
- add `Unit.Traits.CoarseGrained`
2025-06-28 17:06:44 -07:00
Alexander Rose
2f3197479d Merge pull request #1550 from giagitom/illumination-fix
Fix outlines on opaque elements using illumination mode
2025-06-28 16:12:31 -07:00
Alexander Rose
6536d0ab91 Merge branch 'master' into illumination-fix 2025-06-28 16:12:09 -07:00
Alexander Rose
3bee224e7d Merge pull request #1549 from molstar/gl-refactor
WebGL related refactoring
2025-06-28 15:56:00 -07:00
Alexander Rose
3e63137977 Merge branch 'master' of https://github.com/molstar/molstar into gl-refactor 2025-06-28 15:53:29 -07:00
Alexander Rose
38d6bc6c27 tweak 2025-06-28 15:52:43 -07:00
Alexander Rose
fafe22d56b Apply suggestions from code review
Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-06-28 15:45:32 -07:00
giagitom
a6a92bcf91 lint fix 2025-06-28 23:03:39 +02:00
giagitom
82c681f445 improve performances 2025-06-28 23:01:04 +02:00
giagitom
fbbd58b4db Fix isosurface compute shader normals when transformation matrix is applied to volume 2025-06-28 17:34:52 +02:00
David Sehnal
2dc13f082c Add custom extensions to MVS (#1547)
* Add custom extensions to MVS

* typo

* lint
2025-06-24 17:04:01 +02:00
midlik
ab5eb5993d MVS generic color themes (#1530)
* MVS: CategoricalPalette draft

* MVS: tweak param validation for union, nullable

* MVSAnnotationColorTheme: support categorical palette

* MVS: color theme categorical with list or mapping

* MVS: color theme categorical with named palette

* Add missing color lists

* Sort color lists

* MVS: color theme categorical tidyup

* MVS: color theme continuous params

* MVS: color theme continuous impl

* refactor

* MVS: color theme continuous - reverse, auto overflow_color

* MVS: color theme discrete

* file reorg

* MVS: param union does not need []

* MVS: refactor typing object params

* MVS: color theme - palette defaults in one place

* MVS: declare fields_remapping param

* MVS: implement fields_remapping param

* MVS: docs

* Update CHANGELOG

* MVS: rename fields_remapping -> field_remapping

* PR feedback

* MVS: Generic color themes - case_insensitive param

* MVS: SecondaryStructure named color dict

* Remove accidentaly added file

* Update color map descriptions

* Revert color scheme renaming, keep for v5

* Revert "Revert color scheme renaming, keep for v5"

This reverts commit 12e25c20fe.

* Added color list type "cyclical"

* Color palettes - show description in UI tooltips

* Fixed docstrings
2025-06-24 12:48:39 +02:00
Alexander Rose
2384003f5d add https support for dev server (#1548) 2025-06-24 12:41:07 +02:00
David Sehnal
3675c0afe0 Update Representation.Empty creation (#1546) 2025-06-24 12:40:50 +02:00
giagitom
d9bae488e9 Fix outlines on opaque elements using illumination mode 2025-06-23 17:58:53 +02:00
Alexander Rose
e31e5321ba refactor (abstract) webgl drawing buffer handling 2025-06-22 16:43:22 -07:00
Alexander Rose
8c7f8b8a56 remove unused WebGLContext.getDrawingBufferPixelData 2025-06-22 16:38:18 -07:00
Alexander Rose
e4dfb5148c add support for webgl multiview2 extension 2025-06-22 16:35:13 -07:00
Alexander Rose
39e2591b60 improve webgl error handling 2025-06-22 16:31:51 -07:00
David Sehnal
f8a5237024 Improve production build (#1542)
* production build using esbuild

* build browser tests with esbuild

* use tsc-alias

* remove webpack

* changelog

* update eslint to v9

* pr feedback

* update build

* include src map by default
2025-06-17 18:15:10 +02:00
MadCatX
6c2d5b9da7 Do not display NtC Tube and Confal pyramids Loci labels as verbatim text (#1543) 2025-06-16 10:45:08 +02:00
midlik
e128d85356 StringLike type include string explicitely (#1539) 2025-06-12 18:08:56 +02:00
Alexander Rose
08a929bb2f 4.18.0 2025-06-08 13:40:21 -07:00
Alexander Rose
5a54b3ef66 changelog 2025-06-08 13:37:31 -07:00
Alexander Rose
a0c897547a schema updates 2025-06-08 13:37:25 -07:00
Alexander Rose
89ce8394fd package updates 2025-06-08 13:34:08 -07:00
Alexander Rose
ea0331e95c Merge branch 'master' of https://github.com/molstar/molstar 2025-06-08 13:28:12 -07:00
Alexander Rose
9f220b55c2 fix mc scalar field diff (@giagitom) 2025-06-08 13:28:10 -07:00
Alexander Rose
acf248d58f Merge pull request #1535 from molstar/arbitrary-plane-sampling
Support sampling from arbitrary planes
2025-06-08 13:26:34 -07:00
Alexander Rose
c83b859766 type tweak 2025-06-08 13:26:21 -07:00
Alexander Rose
33a2564893 Merge branch 'master' into arbitrary-plane-sampling 2025-06-08 13:25:58 -07:00
David Sehnal
d409c4f5ea Fix SASS @import depraction warnings (#1534)
* refactor SASS to not use @import

* changelog

* typo
2025-06-08 09:33:39 +02:00
Alexander Rose
ab61e31230 header 2025-06-07 16:29:28 -07:00
Alexander Rose
ae9c2dd9d8 Support sampling from arbitrary planes
- structure plane and volume slice representations
2025-06-07 16:27:37 -07:00
David Sehnal
c17edb4928 isolatedModules and fix turbopack build (#1533)
* isolated modules tsconfig & fix errors

* fix mol-math imports

* fix turbopack builds

* fix typo

* tweak

* undo gl-shim change
2025-06-02 18:59:42 +02:00
Alexander Rose
528377eb47 Merge pull request #1532 from molstar/xray-picking
Support `pickingAlphaThreshold` when `xrayShaded` is enabled
2025-06-01 08:48:01 -07:00
Alexander Rose
c9819369d0 header 2025-05-31 11:33:18 -07:00
Alexander Rose
cdbbbfa6dd Support pickingAlphaThreshold when xrayShaded is enabled 2025-05-31 11:29:58 -07:00
David Sehnal
a1e31c79e9 MVS: FoV adjusted position Camera Info & MVSX assets in multi-snapshot states (#1531)
* FoV adjusted position Camera Info

* Fix MVSX file assets being disposed in multi-snapshot states

* pr feedback
2025-05-30 19:19:29 +02:00
midlik
e027fe46c1 MVS: Support for label_comp_id and auth_comp_id in annotations (#1529)
* MVS: Support for label_comp_id and auth_comp_id in annotations

* MVS: Primitives recognize empty substructures, distance_measurement refactor

* MVS: Primitives skipped when empty substructure, nicer default arrow caps

* MVS: Primitive angle_measurement added vector_radius param
2025-05-23 16:17:26 +02:00
dsehnal
05c4006e9d 4.17.0 2025-05-22 07:01:43 +02:00
dsehnal
191ea65c9d changelog 2025-05-22 06:58:02 +02:00
David Sehnal
3c1ee16376 remove salt bridge interaction kind (#1528) 2025-05-22 06:56:15 +02:00
David Sehnal
9ac34ee13b Add mvs-stories app (#1523)
* mvs-stories app

* update mvs-stories example

* fix build

* fix UI bug

* support search params in stories app

* merge fixes

* PR feedback

* customize build filenames

* mvs-stories loading state & dev build script fixes

* multiple context example
2025-05-22 06:49:17 +02:00
midlik
6778452d07 NodeJS ajaxGet support gzip (#1516)
* Retype string to StringLike in parsers

* Define minimal CustomString interface

* ChunkedBigString

* Test ChunkedBigString with cif2bcif

* benchmarking

* ChunkedBigString access optimization

* ChunkedBigString .length optimization

* ChunkedBigString.indexOf, tests

* ChunkedBigString remove [] in favor of charAt

* ChunkedBigString tidy up

* ChunkedBigString .substring optimization

* ChunkedBigString for browser

* ChunkedBigString for drag-and-drop

* ChunkedBigString fixes

* Simplify readFromFileInternal

* Correctly type DataResponse<'string'> as StringLike

* Update CHANGELOG

* PR feedback

* Workaround for ajaxGet in NodeJS when content gzipped

* Workaround for ajaxGet in NodeJS when content gzipped - allow aborting

* ajaxGetInternal_file_NodeJS - async read file

* Eliminate xhr2

* Remove xhr2 dependency

* Update file headers
2025-05-21 14:49:54 +02:00
Alexander Rose
7e01af1e0d 4.16.0 2025-05-20 21:07:34 -07:00
Alexander Rose
85469cbf28 changelog 2025-05-20 21:04:22 -07:00
Alexander Rose
299bdc72cd Merge pull request #1525 from molstar/mp4-export-fix-25-5-20
Fix camera interpolation during animation export
2025-05-20 21:01:41 -07:00
dsehnal
ae9f879139 use isContextLost flag instead of pausing/resuming animation 2025-05-21 05:53:26 +02:00
dsehnal
b50d83d6ea replace behavior subject with subject 2025-05-20 18:02:40 +02:00
dsehnal
2d99d8a1d0 do not pause animation during context loss 2025-05-20 17:32:45 +02:00
midlik
ea00cca1c8 MVS single state loading (#1524)
* MVS: Load single state as if multistate

* MVS: join keepCamera and keepSnapshotCamera options

* MVS: remove replaceExisting, addappendSnapshots option
2025-05-20 17:24:25 +02:00
midlik
27c3b4e698 Big strings (#1479)
* Retype string to StringLike in parsers

* Define minimal CustomString interface

* ChunkedBigString

* Test ChunkedBigString with cif2bcif

* benchmarking

* ChunkedBigString access optimization

* ChunkedBigString .length optimization

* ChunkedBigString.indexOf, tests

* ChunkedBigString remove [] in favor of charAt

* ChunkedBigString tidy up

* ChunkedBigString .substring optimization

* ChunkedBigString for browser

* ChunkedBigString for drag-and-drop

* ChunkedBigString fixes

* Simplify readFromFileInternal

* Correctly type DataResponse<'string'> as StringLike

* Update CHANGELOG

* PR feedback

* PR feedback 2
2025-05-20 11:55:20 +02:00
Alexander Rose
52942e7021 4.15.0 2025-05-19 19:31:09 -07:00
Alexander Rose
5904f694b5 changelog 2025-05-19 19:28:29 -07:00
Alexander Rose
92c0b82784 pckage updates 2025-05-19 19:28:16 -07:00
Alexander Rose
e1226fa384 type fix 2025-05-19 19:27:59 -07:00
Alexander Rose
ac2f7d1c38 lint 2025-05-19 19:27:48 -07:00
Alexander Rose
ae1742f68e Merge pull request #1520 from molstar/fix-contextlost-handling
WebGL ContextLost handling improvements
2025-05-18 14:47:36 -07:00
Alexander Rose
04e2da86fd typo 2025-05-17 16:39:06 -07:00
Alexander Rose
510182ff60 WebGL ContextLost handling improvements
- Fix missing framebuffer & drawbuffer re-attachments
- Fix missing cube texture re-initialization
- Fix missing extensions reset
- Fix timer clearing edge case
- Add reset support for geometry generated on he GPU
2025-05-17 16:36:20 -07:00
Alexander Rose
4e1da19bdd Merge pull request #1506 from sbittrich/master
IHM improvements: Enable assembly symmetry, disable volume streaming and validation report visualization
2025-05-17 13:46:26 -07:00
Alexander Rose
a3eae15446 Merge branch 'master' into master 2025-05-17 13:15:04 -07:00
David Sehnal
4334f4d1fa JSON CIF format and ligand editor example (#1510)
* wip data model and writer

* parser & test

* minimal editor example

* molstar_bond_site cif category support

* ligand graph, deletion, simple undo

* jest config

* bond editing and graph change summary

* readme

* ts config

* basic atom addition

* undo path aliases because tsc doesn't transform them

* tweak package json

* basic rgroup support

* mol parsing test and fixes

* refactoring

* molfile conversion

* refactoring and UI polish

* molfile export tweaks

* move jsonCifToMolfile

* tweak

* refactoring

* error reporting

* geometry edits

* hide selection controls

* refactoring

* tweaks

* changelog

* ligand graph tests

* SingleTaskQueue tweak

* revert Column changes

* pr feedback

* PR Feedback
2025-05-13 10:51:39 +02:00
Alexander Rose
e33ed54121 Merge pull request #1513 from midlik/fix-transparent-ssao-nodejs
Fix transparency rendering with occlusion in NodeJS
2025-05-10 08:51:41 -07:00
Adam Midlik
ae8f037192 Fix transparency rendering with occlusion in NodeJS 2025-05-09 14:12:31 +01:00
Alexander Rose
01271941dd Merge pull request #1509 from molstar/tweak-auto-quality-surface-res
adjust max resolution for auto quality
2025-05-08 22:08:33 -07:00
dsehnal
7f8be5b8c6 4.14.1 2025-05-09 07:02:52 +02:00
David Sehnal
2ab6e4b2e7 No error in Transformer.create (#1512)
* No error in Transformer.create

* header
2025-05-09 06:59:15 +02:00
Sebastian Bittrich
aa22840b12 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	CHANGELOG.md
2025-05-08 10:36:30 -07:00
Sebastian Bittrich
c1e33fac94 PR feedback: adjust assembly symmetry logic 2025-05-08 10:23:58 -07:00
Sebastian Bittrich
a7336095ca name IHM assemblies "deposited" 2025-05-07 09:47:26 -07:00
dsehnal
4a88546181 changelog 2025-05-07 16:08:17 +02:00
dsehnal
edbc70cf6e 4.14.0 2025-05-07 16:07:49 +02:00
dsehnal
c22ad2910c npm audit 2025-05-07 16:04:36 +02:00
dsehnal
28a2b52e3c changelog 2025-05-07 16:03:53 +02:00
David Sehnal
449d572ed5 Merge branch 'master' into tweak-auto-quality-surface-res 2025-05-07 14:50:09 +02:00
Gianluca Tomasello
470227af43 Avoid grid expansion when requiring unit cell on volume server (#1502)
* Avoid grid expansion when requiring unit cell on volume server

* Increment version and use specific changelog

* change header
2025-05-07 14:49:08 +02:00
dsehnal
a0ccf46939 remove extra import 2025-05-05 08:10:03 +02:00
dsehnal
0ce8931fc5 Fix switching representation type in Volume UI 2025-05-04 18:28:19 +02:00
David Sehnal
3ddb29fc6f Add format selection option to image export UI (#1504)
* Add format selection option to image export UI

* check if webp is supported
2025-05-04 14:54:17 +02:00
Alexander Rose
1a0c65df21 changelog 2025-05-03 08:26:01 -07:00
Alexander Rose
daad1923ea adjust max resolution for auto quality (#1501) 2025-05-03 08:22:56 -07:00
David Sehnal
f34f879cf1 MVS: support updating transform states (#1505)
* MVS: support updating transform states

* changelog

* changelog

* pr feedback

* util functions & is_hidden extension
2025-05-02 12:53:38 +02:00
Sebastian Bittrich
f47b76c8af Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	CHANGELOG.md
2025-05-01 11:17:52 -07:00
Sebastian Bittrich
6ee9eb8b60 IHM: disable validation report 2025-05-01 11:16:53 -07:00
Sebastian Bittrich
915703a46d IHM: enable assembly symmetry 2025-05-01 11:13:46 -07:00
Sebastian Bittrich
61c3c19ae3 IHM: disable volume streaming 2025-05-01 11:11:50 -07:00
David Sehnal
6da9557531 Fix StructConn.residueCantorPairs (#1500) 2025-05-01 11:29:24 +02:00
Paul Lewallen
29e6d69d21 Update package.json (#1497)
Add engines field to specify required Node.js version (>=18.0.0)
2025-04-26 07:46:50 +02:00
David Sehnal
6b2b87e6c5 fix Viewer.loadTrajectory (#1496) 2025-04-24 10:44:59 +02:00
dsehnal
5299d5c0c4 changelog 2025-04-14 18:37:52 +02:00
dsehnal
7bab95f4cc 4.13.0 2025-04-14 18:04:43 +02:00
David Sehnal
35e78ce638 MVS Stories (#1484)
* ability to select a story

* rename to mvs-stories

* update kinase story

* fix ae example

* tweaks

* tweak
2025-04-14 18:00:37 +02:00
Chetan Mishra
3abbcb6949 added toggle for hiding screenshot controls (#1483)
* added toggle for hiding screenshot button

* whoops did the todolist but forgot to commit

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-04-14 14:38:47 +02:00
David Sehnal
c3fc893ad0 mvs: fix state builder for volumes (#1485) 2025-04-13 13:07:52 +02:00
midlik
80415a2771 MVS: support loading extensions when loading multistate files (#1470)
Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-04-01 07:15:26 +02:00
etongfu
bfef69e2e4 Dev script update (#1473)
* feat: support host option for build-dev script

* feat: ust update the code related to the host

---------

Co-authored-by: tongfu.e <tongfu.e@xtalpi.com>
2025-04-01 07:14:39 +02:00
David Sehnal
a265a579be Update support for QA metrics (#1476)
* generalize ma_qa_metric support

* do not assume PAE is symmetric

* changelog

* Update src/extensions/model-archive/quality-assessment/prop.ts

Co-authored-by: Alexander Rose <alexander.rose@weirdbyte.de>

* Update src/extensions/model-archive/quality-assessment/prop.ts

Co-authored-by: Alexander Rose <alexander.rose@weirdbyte.de>

* lint

---------

Co-authored-by: Alexander Rose <alexander.rose@weirdbyte.de>
2025-03-31 18:51:18 +02:00
ludovic autin
c2af1b0b22 Colors from user and file (#1466)
* color, and granularity for selectrion.

* Load json colors per ingredient {"name":{"x":0,"y":0,"z":0}}

* change icon

* use functional components and simple function.
2025-03-28 18:51:42 +01:00
Sagar Pathak
b739876726 Update index.md (#1472)
Fix command typo: changed 'npm build' to 'npm run build'
2025-03-24 17:57:01 +01:00
David Sehnal
56851cc328 Improve struct_conn handling (#1468)
* improve struct_conn handling

* fix

* fix

* check same model

* Update src/mol-model-formats/structure/property/bonds/struct_conn.ts

Co-authored-by: Alexander Rose <alexander.rose@weirdbyte.de>

---------

Co-authored-by: Alexander Rose <alexander.rose@weirdbyte.de>
2025-03-24 16:49:11 +01:00
dsehnal
b719568555 mobile-friendly Kinase Story 2025-03-24 08:47:42 +01:00
Alexander Rose
f842f19912 Merge branch 'master' of https://github.com/molstar/molstar 2025-03-23 16:28:55 -07:00
Alexander Rose
d6b0dd910c guard against overly large grids 2025-03-23 16:28:52 -07:00
Alexander Rose
395eb8e8d0 Merge pull request #1454 from agdturner/pwa
For viewer to be installable as a Progressive Web App with a Service …
2025-03-23 16:28:03 -07:00
Alexander Rose
e4376c6737 try fix package-lock 2025-03-23 16:10:03 -07:00
Alexander Rose
6f23fcba8a Merge branch 'master' of https://github.com/molstar/molstar into pr/agdturner/1454 2025-03-23 16:06:17 -07:00
dsehnal
7d19bfdb9b Tweaks: kinase story edgecase fix, do not include volseg extension in Viewer by default 2025-03-17 09:30:30 +01:00
David Sehnal
6e4065f779 Interactions extension (#1463)
* move schema based element addressing from MVS to the core library

* proof of concept

* tweak

* initial visual

* tweak

* tweak structureElementLocationToSchemaItem

* show receptor residues as ball and stick

* wip data model

* custom interactions support

* add example

* wip visuals

* covalent links

* tweak

* fix bug

* cache unit features

* Add structureRef to Molecule.Structure.Selections

* optimize compute

* support multi-structure selections

* analyzeTrajectory support

* readme

* tweak

* headers

* docs

* Optimize StructureElementSchema & remove fromLoci conversion (not production ready for now, will be separate PR)

* move schema code to `StructureElement.Schema` and add fromExpression/Query/Schame functions to Loci and Bundle

* improve selection docs

* adjust covalent bond data model

* tweak fromExpression

* fix type

* remove hydrogen reference

* Fix MVS.rowsToExpression
2025-03-17 09:25:18 +01:00
Alexander Rose
c42a68b560 fix package-lock 2025-03-15 16:44:16 -07:00
Alexander Rose
c86d913b83 Merge branch 'master' of https://github.com/molstar/molstar into pr/agdturner/1454 2025-03-15 16:42:38 -07:00
Alexander Rose
0f6fa5fe15 simplify, add pwa files during deploy 2025-03-15 16:38:04 -07:00
Alexander Rose
f664cb02b1 Fix pickPadding and pickScale not updating PickHelper 2025-03-15 14:34:47 -07:00
David Sehnal
00a53de6e2 Use StructureElement.Bundle for measurements (#1453)
* Revert "Support measurements for coarse models"

This reverts commit a8a84e1dbf.

* add MultiStructureSelectionFromBundle and use it for measurements
2025-03-12 07:15:03 +01:00
Paul Pillot
b1ce5c158e fix: bond iterator starts from the same interbonds for every element (#1464)
This is causing an issue when there are multiple units having different inter-unit bonds: the `interBondCount` value is based on the `interBondIndices` length which is correct. But the iteration always starts from the `edges` index === 0. This is only correct for the first pairs of units. The iteration must be done over the `interBondIndices` to get the proper edges.

By returning indices for edges that do not correspond to the given element, the `otherIndex` property can be of bounds.
2025-03-12 06:41:59 +01:00
dsehnal
26826b61f9 fix lint error 2025-03-10 11:06:06 +01:00
Lukas Polak
f44f954a76 Implement ColorScale.createDiscrete, fix UI color palette bugs (#1459) 2025-03-09 10:53:10 +01:00
Alexander Rose
78aae8a2b4 pwa tweaks
- keep build process simple, write SW in JS
- support molstar version SW
- add `Viewer.loadFiles` to open supported files
- cleanup pwa icons
- add more file_handlers to pwa manifest
2025-03-08 15:00:23 -08:00
David Sehnal
92267d3264 MVS example tweaks (#1457)
* kinase story

* ihm-restraints

* fix typo

* tweak wwpdb links
2025-03-05 15:46:33 +01:00
Andy Turner
73ed45564e For viewer to be installable as a Progressive Web App with a Service Worker transpiled from TypeScript 2025-03-04 09:05:51 +00:00
David Sehnal
8bc2ebbeff Experimental esbuild support (#1452)
* wip esbuild

* esbuild all apps and examples

* wip dev build

* dev builds

* tweaks
2025-03-04 07:22:44 +01:00
Alexander Rose
5306d5d15a ignore renderables with empty draw count 2025-03-01 14:04:33 -08:00
Alexander Rose
3c3fb461c8 fix element-point visual not using child unit 2025-03-01 14:03:31 -08:00
dsehnal
62b3281282 fix webpack config 2025-03-01 19:20:34 +01:00
dsehnal
e85fadf15b tweak 2025-03-01 13:14:45 +01:00
dsehnal
a8a84e1dbf Support measurements for coarse models 2025-03-01 13:11:50 +01:00
David Sehnal
153599ef89 ihm-restraints example: show entity labels (#1450)
* ihm-restraints example: show entity labels

* noEntityLabels option
2025-03-01 08:37:51 +01:00
dsehnal
b67eda7cb5 4.12.1 2025-02-28 08:11:41 +01:00
dsehnal
8b431c50be npm fix 2025-02-28 08:08:58 +01:00
dsehnal
e195b048a1 4.12.0 2025-02-28 08:04:38 +01:00
dsehnal
ae5bb81b27 changelog 2025-02-28 08:01:21 +01:00
David Sehnal
8c04c57bc5 MVS Animation example (#1444)
* wip kinase story

* wip storyboard

* wip kinases

* import

* tweaks

* finish kinase story

* refactoring

* changelog

* tweaks

* tweak
2025-02-27 19:41:18 +01:00
David Sehnal
ec46a444f1 I/HM Example Improvements (#1448)
* add CoarseIndex

* IHM validation snapshots

* tweaks

* header
2025-02-25 06:44:48 +01:00
Alexander Rose
559e0326b6 fix image/slice group handling
- correctly update group count
- ignore undefined group when picking
- ensure group cover anti-aliased slice part
2025-02-22 11:06:01 -08:00
Sebastian Bittrich
82b93bc2a8 prim: fix arrow orientation and behavior along [0,-1,0] (#1447) 2025-02-22 09:11:59 +01:00
David Sehnal
62f940bc48 MVS: angle primitive (#1446) 2025-02-21 18:44:23 +01:00
David Sehnal
4e0be8e7b4 MVS: Volume Server support + Support carbohydrate representation + Camera section in Screenshot / State (#1445)
* MVS: Volume Server support + Camera section in Screenshot / State

* support carbohydrate repr
2025-02-21 07:51:10 +01:00
David Sehnal
128502edf0 MVS: Basic volumetric data support (#1443)
* mvs: basic volumetric data support

* headers
2025-02-19 09:03:04 +01:00
David Sehnal
aad4d4a86c MVS: IHM support (#1433)
* MVS: IHM support

* pr feedback

* fix cyclic import

* ihm.overlaps-seq-id-range

* Add ihm-restraints example
2025-02-18 08:18:18 +01:00
Alexander Rose
9bc7e27243 Merge pull request #1419 from molstar/slice-rotate
Add support for rotating `slice` representation around an axis & structure plane representation
2025-02-17 18:05:05 -08:00
Alexander Rose
a5111356c1 Add transform property to clip objects 2025-02-17 17:59:14 -08:00
Alexander Rose
9b11f7ffde use defaultColor for NaN values 2025-02-16 13:30:11 -08:00
Alexander Rose
93ce6d2807 Merge branch 'master' of https://github.com/molstar/molstar into slice-rotate 2025-02-16 13:27:56 -08:00
Alexander Rose
5c9d5d3a3d fix Vec3 prop check in setUpdateState 2025-02-16 13:27:09 -08:00
David Sehnal
f40307db39 Remove static uses of ColorTheme and SizeTheme fields (#1442) 2025-02-16 18:17:01 +01:00
Alexander Rose
4e6000fa6c Merge branch 'master' of https://github.com/molstar/molstar into slice-rotate 2025-02-15 16:59:16 -08:00
Alexander Rose
26e5817bf2 slice & plane-image improvements
- support trimming & rotation for boxes with non 90 deg angles
- cleanup & document params
2025-02-15 16:57:35 -08:00
Alexander Rose
8469be80d0 fix uniform slice coloring out of bounds 2025-02-15 16:40:05 -08:00
David Sehnal
029edc95c8 MVS: Additional Primitives (#1437)
* ellipsis

* box

* improve ellipsis

* improve ellipsis

* arrow primitive

* tweak arrow

* ellipsoid

* changelog

* pr feedback
2025-02-12 16:33:06 +01:00
David Sehnal
dd9aaf055f Components example (#1425)
* components example, initial code

* refactoring

* readme

* usage example

* changelog

* tweak
2025-02-11 18:08:15 +01:00
Alexander Rose
fcfb2d940c Merge branch 'master' of https://github.com/molstar/molstar into slice-rotate 2025-02-09 14:06:29 -08:00
Alexander Rose
f5b5109d0f Improve logic when to cull in renderer 2025-02-01 19:13:59 -08:00
Sebastian Bittrich
ca99c800f1 fix PDBj structure data URL (#1430) 2025-01-31 08:13:52 +01:00
Alexander Rose
dbd5570370 4.11.0 2025-01-26 11:10:06 -08:00
Alexander Rose
3f805c7a82 changelog 2025-01-26 11:07:06 -08:00
Alexander Rose
12c71dc5ba Handle Firefox's limit on vertex ids per draw 2025-01-25 16:04:34 -08:00
Alexander Rose
2fe3a926aa package updates 2025-01-25 15:59:44 -08:00
Alexander Rose
60c2096575 scss tweak 2025-01-25 15:53:52 -08:00
Alexander Rose
f4e9df5e4d schema updates 2025-01-25 15:26:06 -08:00
Alexander Rose
c304b82772 changelog 2025-01-25 15:18:39 -08:00
Alexander Rose
9edd171350 Merge pull request #1421 from molstar/volume-dot
add volume dot representation
2025-01-25 15:16:36 -08:00
Alexander Rose
f7d1bd7c04 PR tweaks 2025-01-25 14:27:59 -08:00
Alexander Rose
7422c255ab Merge branch 'master' of https://github.com/molstar/molstar into volume-dot 2025-01-25 14:26:44 -08:00
Alexander Rose
5497215784 Merge pull request #1423 from giagitom/fix-cartoon-tubular-helices
Fix tubular helices issue
2025-01-25 14:25:40 -08:00
giagitom
577bf1c77c Fix tubular helices issue 2025-01-22 16:27:40 +01:00
David Sehnal
c9bddccaf7 MVS: Initial support for customizable representation parameters (#1417)
* MVS: Initial support for customizable representation parameters

* pr feedback
2025-01-21 13:53:24 +01:00
midlik
ac292f9267 Sequence panel focus marker (#1392)
* Sequence view show focused residues

* wip

* Factor out MarkerColors

* Marker array supports "focus" marker type

* Sequence panel - separate focus marker from highlight and select

* Revert changes in mol-util/marker-actions.ts

* Simplify sequence.tsx

* Sequence panel markers follow renderer highlight colors

* Sequence panel focused range in bold

* Focus add with Ctrl, extend with Shift

* Update CHANGELOG
2025-01-21 13:15:06 +01:00
Alexander Rose
f0b8d75b10 add volume dot representation
- add volume-value size theme
2025-01-19 17:47:21 -08:00
Alexander Rose
0dacbcb3bc fix vertex based themes for spheres shader 2025-01-19 17:45:52 -08:00
Alexander Rose
0789241ea3 Add plane structure representation
- Can be colored with any structure theme
- Can be colored with the `external-volume` theme
- Can show atoms as a cutout
- Supports principal axes and bounding box as a reference frame
2025-01-18 19:36:49 -08:00
Alexander Rose
ddb0799dc4 Merge branch 'master' of https://github.com/molstar/molstar into slice-rotate 2025-01-18 17:30:36 -08:00
Alexander Rose
cbfa341fa3 Merge pull request #1411 from midlik/quick-styles
Quick styles
2025-01-18 16:57:03 -08:00
Alexander Rose
1c19bd90df Merge branch 'master' into quick-styles 2025-01-18 16:56:56 -08:00
Alexander Rose
300e5c8985 Merge pull request #1407 from sbittrich/master
Rebrand PDB-Dev as PDB-IHM
2025-01-18 16:55:24 -08:00
Alexander Rose
0861a78db6 Merge branch 'master' into master 2025-01-18 16:55:08 -08:00
Alexander Rose
a8e403ad85 Add support for rotating slice representation around an axis
- Add default color support for palette based themes
- Add support for trimming `image` geometry to a box
- Improve/fix iso-level support of `slice` representation
2025-01-18 16:45:22 -08:00
Ventura Rivera
4e350496b2 Sequence Viewer Mode Customization (#1412)
* adding flags for viewport selection controls

* adding logic to remove/keep selection controls

* adding viewport selection control feature

* package updates

* moving selectionTool options out of viewport

* updating selection controls with new properties

* updating property name to match nomenclature

* adding option for custom selection controls

* adding custom selection controls

* minor property name update

* adding property for granularity options

* reassigning StructureSelectionParams.granularity.options if custom granularity options

* adding entry for custom granularity options

* reusing Loci.Granularity to specify valid strings for granularityOptions

* Update src/mol-plugin-ui/spec.ts

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>

* merging molstar/molstar:main into ventura-rivera/molstar:main

* moving granularityOption logic into componentDidMount

* moving granularityOption logic to componentDidMount and creating structureSelectionParams state

* adding modeOptions and defaultMode properties to sequenceViewer

* adding logic to customize mode controls

* CHANGELOG

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-01-18 10:59:07 +01:00
Alexander Rose
dd21ddcc80 math helpers 2025-01-17 22:47:42 -08:00
Alexander Rose
a88121f779 add Quat uniform mapping to vec4 2025-01-17 22:47:27 -08:00
Adam Midlik
1ab91d1979 Quick Styles: stateless UI 2025-01-17 11:17:14 +00:00
Adam Midlik
267788388d Quick Styles: UI subsection headers 2025-01-17 10:11:52 +00:00
Adam Midlik
43c0333be3 Quick Styles: postpone UI update while animation running 2025-01-14 10:33:25 +00:00
JonStargaryen
3b90a269b0 rebranding from PDB-Dev to PDB-IHM 2025-01-13 11:21:00 -08:00
Ventura Rivera
4aa5e1d7fc Structure Selection Granularity Options Customization (#1410)
* adding flags for viewport selection controls

* adding logic to remove/keep selection controls

* adding viewport selection control feature

* package updates

* moving selectionTool options out of viewport

* updating selection controls with new properties

* updating property name to match nomenclature

* adding option for custom selection controls

* adding custom selection controls

* minor property name update

* adding property for granularity options

* reassigning StructureSelectionParams.granularity.options if custom granularity options

* adding entry for custom granularity options

* reusing Loci.Granularity to specify valid strings for granularityOptions

* Update src/mol-plugin-ui/spec.ts

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>

* merging molstar/molstar:main into ventura-rivera/molstar:main

* moving granularityOption logic into componentDidMount

* moving granularityOption logic to componentDidMount and creating structureSelectionParams state

---------

Co-authored-by: David Sehnal <dsehnal@users.noreply.github.com>
2025-01-13 16:39:25 +01:00
Adam Midlik
679db48938 Merge branch 'master' into quick-styles 2025-01-13 15:09:42 +00:00
Adam Midlik
2f96b42df7 Updated CHANGELOG 2025-01-13 15:08:12 +00:00
Adam Midlik
dd6f3bd76e Increase scrollbar visibility 2025-01-13 14:41:38 +00:00
Adam Midlik
f1b7e478c7 Remove unused stuff 2025-01-13 13:32:02 +00:00
Adam Midlik
416442aa27 entity-id color theme overrideWater param 2025-01-13 11:59:36 +00:00
Alexander Rose
a5f65b6e6f use value for uniform coloring of slices
- recovers previous behavior
2025-01-12 18:10:14 -08:00
Alexander Rose
938ac0cc8f fix image rendering issues with marking
- handle pixels without a group
- take fog into account
2025-01-11 14:47:06 -08:00
Alexander Rose
7dacf60478 plane mesh helpers 2025-01-11 14:40:16 -08:00
Alexander Rose
9cdb8a3a92 Merge pull request #1399 from molstar/improve-volume-coloring
improve volume coloring
2025-01-11 14:35:17 -08:00
Alexander Rose
242982e661 Merge branch 'master' into improve-volume-coloring 2025-01-11 14:34:58 -08:00
Alexander Rose
6da20a6989 Fix Plane3D.projectPoint 2025-01-11 09:21:33 -08:00
Alexander Rose
f27b651230 tweak spec.components.selectionTools.hide names 2025-01-11 09:17:30 -08:00
Alexander Rose
7c818c0cc9 add location related comments 2025-01-11 08:58:59 -08:00
Adam Midlik
e7d7ba26b0 Quick Styles: Add cartoon 2025-01-10 16:16:36 +00:00
Adam Midlik
7e64121059 Quick styles: two-row UI 2025-01-10 15:59:20 +00:00
Adam Midlik
894bba1d3a Quick styles: Stylized independent from preset 2025-01-10 11:14:23 +00:00
Adam Midlik
d9db775fe8 Toggle button different hover color when on and off 2025-01-10 11:07:13 +00:00
Ventura Rivera
a7fbc7b4c4 Remove viewport selection controls (#1408)
* adding flags for viewport selection controls

* adding logic to remove/keep selection controls

* adding viewport selection control feature

* package updates

* moving selectionTool options out of viewport

* updating selection controls with new properties

* updating property name to match nomenclature

* adding option for custom selection controls

* adding custom selection controls

* minor property name update
2025-01-10 11:06:14 +01:00
Alexander Rose
c0596298d6 Add support for position-location to volume-value color theme 2025-01-04 09:26:30 -08:00
Alexander Rose
8f32dde599 review tweaks 2025-01-04 09:25:01 -08:00
Alexander Rose
4d8f00900d improve volume coloring
- Add `volume-data` theme that colors positions by volume data
- Add support for color themes to `slice` representation
- Improve/fix palette support in volume color themes
2025-01-03 17:07:13 -08:00
828 changed files with 64835 additions and 26484 deletions

View File

@@ -1,4 +0,0 @@
node_modules/*
build/*
docs/site/*
lib/*

View File

@@ -1,122 +0,0 @@
{
"env": {
"browser": true,
"node": true
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"ecmaFeatures": {
"impliedStrict": true
}
},
"rules": {
"indent": "off",
"arrow-parens": [
"off",
"as-needed"
],
"brace-style": "off",
"comma-spacing": "off",
"space-infix-ops": "off",
"comma-dangle": "off",
"eqeqeq": [
"error",
"smart"
],
"import/order": "off",
"no-eval": "warn",
"no-new-wrappers": "warn",
"no-trailing-spaces": "error",
"no-unsafe-finally": "warn",
"no-var": "error",
"spaced-comment": "error",
"semi": "warn",
"no-restricted-syntax": [
"error",
{
"selector": "ExportDefaultDeclaration",
"message": "Default exports are not allowed"
}
],
"no-throw-literal": "error",
"key-spacing": "error",
"object-curly-spacing": ["error", "always"],
"array-bracket-spacing": "error",
"space-in-parens": "error",
"computed-property-spacing": "error",
"prefer-const": ["error", {
"destructuring": "all",
"ignoreReadBeforeAssign": false
}],
"space-before-function-paren": "off",
"func-call-spacing": "off",
"no-multi-spaces": "error",
"block-spacing": "error",
"keyword-spacing": "off",
"space-before-blocks": "error",
"semi-spacing": "error",
"no-constant-binary-expression": "error"
},
"overrides": [
{
"files": ["**/*.ts", "**/*.tsx"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": ["tsconfig.json", "tsconfig.commonjs.json"],
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/class-name-casing": "off",
"@typescript-eslint/indent": [
"error",
4
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/prefer-namespace-keyword": "warn",
"@typescript-eslint/quotes": [
"error",
"single",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/brace-style": [
"error",
"1tbs", { "allowSingleLine": true }
],
"@typescript-eslint/comma-spacing": "error",
"@typescript-eslint/space-infix-ops": "error",
"@typescript-eslint/space-before-function-paren": ["error", {
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}],
"@typescript-eslint/func-call-spacing": ["error"],
"@typescript-eslint/keyword-spacing": ["error"]
}
}
]
}

14
.git-blame-ignore-revs Normal file
View File

@@ -0,0 +1,14 @@
# added semicolons to linting rules
fb0634a0f4aab3764b7e6368e38d8dea7615e591
# new linting rules (no default exports, no named tuples)
6c5224f33e9de20fe9967a82536c269bacf29738
# lint: add space-in-parens rule
1d21787e7ea1971817813c008351541e4640c261
# lint: add object-curly-spacing rule
b31302ba3ad4ab7f98aedd500b762be642374ff0
# fix eslint warnings
3b1513adc0048dc4879f1d70874b3e56aaffd10e

View File

@@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18
node-version: 20
- run: npm ci
- run: sudo apt-get install xvfb
- name: Lint

7
.gitignore vendored
View File

@@ -1,4 +1,5 @@
build/
deploy/
lib/
docs/site/
@@ -11,4 +12,8 @@ tsconfig.commonjs.tsbuildinfo
*.sublime-workspace
.idea
.DS_Store
.DS_Store
tmp/
dev.pem
dev-key.pem

View File

@@ -6,9 +6,4 @@
"*.vert.ts": "glsl",
"*.gql.ts": "graphql"
},
"eslint.options": {
"overrideConfig": {
"ignorePatterns": ["webpack.config.js", "scripts/*"],
},
}
}

View File

@@ -4,18 +4,549 @@ All notable changes to this project will be documented in this file, following t
Note that since we don't clearly distinguish between a public and private interfaces there will be changes in non-major versions that are potentially breaking. If we make breaking changes to less used interfaces we will highlight it in here.
## [Unreleased]
- Fix exported image artifacts on transparent background with emissive, bloom, or antialiasing
- Fix cel-shaded ambient color being stripped to luminance (now uses full RGB, matching the classic lighting path)
- Fix empty transforms default in `ShapeFromPly`
- Use morton order for spheres in dot visual with lod-levels
- Add `Camera.changed` event and rotation/translation setter/getter
- Add `instanceGranularity: 'auto'` as a memory guard
- Honor `instanceGranularity` in `Visual.getLoci`
- Add mesoscale representation preset
- Add presets option to `ObjectList` param definition
- Fix memory leak in `State.dispose()` not invoking transformer `dispose` callbacks for live cells
- Fix bugs in ModelServer surroundingLigands endpoint, resulting in omitWater not honored
- Fix `Volume` and `Isosurface` getBoundingSphere ignoring instances
- Fix SSAO half/quarter resolution textures for multi-scale
- Camera improvements
- Add the option to approximate "least obstructed direction" when focusing camera, accessibe via `PluginContext.managers.camera.focusLoci` with `optimizeDirection` option
- Add `CameraFocusOptions.zoomOut` option that zooms out to to make the entire scene visible before focusing on the target
- Add easing support in camera transtion
## [v5.9.0] - 2026-05-03
- Fix edge case when `PluginSpec.animations` is empty
- Add 8K UHD option to `ViewportScreenshotHelper`
- Handle MRC files with empty length header fields
- Handle CCD bonds with Deuterium atoms
- [Breaking] ComponentBond.Entry.map now returns ComponentBond.Pairs
- Fix volume slice marking performance regression
- Add GPU procedural animation (wiggle & tumble)
- Per-vertex wiggle via fbm noise (position & group mode)
- Per-instance tumble via fbm noise (rotation + translation)
- `Wiggle` theme layer for data-driven per-group wiggle
- `enableAnimation` Canvas3D param for global toggle
- Add `AnimateTime` built-in for, e.g., exporting procedural animation
- Add Procedural Animation panels
- Viewer: structure dynamics & uncertainty
- Mesoscale Explorer: entity dynamics
- Fix `GraphQLClient` missing required headers
- [Breaking] Use Record instead of Array for headers (assets & data-source utils)
## [v5.8.0] - 2026-04-03
- Dependencies: remove `utils.promisify`, `node-fetch` (#1797)
- Fix circular dependency which causes crash in bundlers (#1791)
- Add `putty` as a mol-view-spec representation.
- Fix detecting sidechain-only structures as coarse-grained (#1420)
- Fix clip-object transform due to missing axis normalization
- Sequence alignment: Fix return type & improve scoring for unknown residues
- Use PDB SEQRES block to show unresolved residues in Sequence toolbar
- Canvas3D debug-helpers
- [Breaking] Move helpers to an extension as a PluginBehavior (params are no longer part of Canvas3D)
- Add helpers for clip-object, direct-volume, image, mesh
- Fix StructureComponent node update throwing error when substructure empty
- CSS: Avoid tooltip box flickering when hovering something under it
- Volume slice visual
- Fix support for volume instances
- Fix plane mode: ensure normalized & correctly oriented
- MolViewSpec
- Add `VolumeStreamingExtension` (`molstar_volume_streaming` custom property)
- Fix focusing empty selections
- Avoid re-calculating static model properties for trajectories
## [v5.7.0] - 2026-02-28
- Text label improvements
- Improve label background vertical centering
- Handle label depth variant for correct transparent background
- Draw border under text using fragment depth to prevent overlap on adjacent characters
- Clamp border width to avoid exceeding SDF range
- Increase font atlas quality (2x font size multiplier)
- TM-align performance improvements (#1745)
- Disable transparent outline close to opaque elements
- Add axis param to trackball spin & rock animation
- Color smoothing fixes (#1747)
- Use correct instance for non instance-type
- Never transform for non instance-type
- Add extra radius to gaussian surface boundingsphere
- MolViewSpec
- Add `MVSData.toMVSX` function and `mvs-mvsj-to-mvsx.js` CLI utility
- [Breaking] Add PQR file format support (#157)
- Replace `isPdbqt` with `variant` param in `TrajectoryFromPDB`
- Add `CustomVolumeProperty` (like for models and structures)
- Geometry export
- Fix missing `usePalette` support
- Fix vertex-based coloring for non-mesh geometries
- Support line-strips
- Support vertex-based sizing
- Support memory efficient line-strips in Lines geometry,
- Add `StripLinesBuilder`
- Add `computeFrenetFrames` helper
- Streamlines support
- Add basic calculation method
- Add custom-volume-property
- Add representation with lines and tube-mesh visuals
- Fix `TextCtrl` always moving cursor to end position
- Add `vertex` and `vertexInstance` granularity support for size themes
- Add `transform` and `domain` parameters to volume-value size theme
- Fix parsing of single charge type_symbols (e.g., N+) in cif-core
- Detect metal-coordination when parsing pdb
- Handle additional elements in `guessElementSymbol*` (As, Li, Ga)
- Add more element-pair thresholds for bonding (Ag-S, CoSb, Ga-F)
- Add `metalCoordination` style param (dashed, solid) for bonds
- Fix `unitSymmetryGroups` for representations with `includeParent` enabled
- Add `convexHull` helper
- Add `Structure.coordination` sites
- Add `Polyhedron` representation showing coordination sites
- Guard against `xr-spatial-tracking` blocked in `Permissions-Policy`
## [v5.6.1] - 2026-01-23
- Disable occlusion culling in `ImagePass` (#1758)
- MolViewSpec
- Fix `MVSAnnotationStructureComponent` not updating properly when parent structure changes
## [v5.6.0] - 2026-01-18
- Handle Hex codes that are submitted with alpha channels by ignoring the alpha channel (#1746)
- Only show "already registered transformer" warnings in non-production builds
- Fix `label_seq_id` assignment in PDB parser to use 1-based linear indexing (#1730) if:
- when insertion codes are present
- `SEQRES` records are present
- Viewer app
- Add `action: 'focus'` support to `Viewer.structureInteractivity`
- Add `viewportFocusBehavior: 'secondary-zoom'`
- MolViewSpec
- Validation treats `undefined` same as missing value
- Increase default size of `carbohydrate` representation
- `color_from_uri` and `color_from_source` take `selector` parameter
- Add `keepCameraOrientation` option for loading functions
- `label_from_*` and `tooltip_from_*` take `text_format` parameter
- `label_from_*` take `group_by_fields` parameter
- Tweak Gaussian Density smoothness default range (less artefacts)
- Support `includeParent` for Gaussian Surface (disables GPU support)
- Support floodfill before surface extraction (`off`, `interior`, `exterior`)
- For Isosurface, Molecular Surface, Gaussian Surface
- Fix `to_mmCIF` writing duplicate categories under certain conditions (#1738)
- Add stable random number generator (PCG)
- ME grayscale colors; dot offset; SSAO hemisphere vectors
- Use blue noise for SSAO hemisphere vectors
- Fix SSAO darkening when sampling background/offscreen pixels
- Adding structure wireframe visuals on molecular and gaussian surfaces
- Fix caching of `__srcIndexArray__`
- Prevent self-occlusion on quaternary amine
- Fix outline postprocessing artifacts (black bands) on membrane layers at grazing view angles in Illustrative mode (#1749)
- Remove fence from `Canvas3D.render` to not interfer with `requestAnimationFrame`
- Fix boundingSphere reuse in structure visuals (was triggering extra calculation)
- Use PDB seqres record to deduce entity information
- Add lipid components names used in amber ff
## [v5.5.0] - 2025-12-22
- Viewer app
- Move viewer extensions, options, and presets to a separate file
- Add `molstar.lib` export providing access to a wide range of functionality previously not available from the compiled bundle
- Add `Viewer.subscribe` method that keeps track of subscribed plugin events and disposes them together with the parent viewer
- Add `Viewer.structureInteractivity` that makes it easy to highlight/select elements on the loaded structure
- Add `viewportBackgroundColor` and `viewportFocusBehavior` options
- Add `mvs.html` example to showcase the new functionality combined with MolViewSpec
- Add dark and blue color theme support (import `theme/dark.css` or `theme/blue.css` instead of the default `molstar.css`)
- MolViewSpec extension
- Add `tryGetPrimitivesFromLoci` that makes it easier to access primitive element data from hover/click interactions
- Add `getCurrentMVSSnapshot` to obtain source data for the currently displayed snapshot
- Add TM-align structure-based protein alignment algorithm
- New `TMAlign` namespace in `mol-math/linear-algebra/3d/tm-align.ts`
- New `tmAlign` function in `mol-model/structure/structure/util/tm-align.ts`
- Returns TM-score, RMSD, alignment mapping, and transformation matrix
- Molecular Surface
- Fix "auto" quality params not hidden
- Fix calculation when probe diameter is smaller then resolution
- Fix webgl1 shader syntax
- Fix program not compiled for sync picking
- Fix missing `gl.flush` for async picking (needed for Safari)
- Add Residue Charge color scheme (#1722)
- Add dropdown indicator for mapped parameter definitions and adjust "more options" icon
- Fix `flipSided` for meshes
- [Breaking] Interior coloring
- Remove global `interiorDarkening`, `interiorColorFlag`, `interiorColor`
- Add per-geometry `interiorColor`, `interiorSubstance`
- Add `label/auth_comp_id` to `StructureProperties.residue`
- Previously, this has been only been present on `.atom` (since residue name can alter on per-atom basis), but this has been a bit confusing for the general use-case
- Move canvas "checkered background" logic to `canvas3d.ts` and only apply it when `transparentBackground` is on
- This prevents ugly flickering during plugin initialization
- Fix unit hash collision issues (#1721)
## [v5.4.2] - 2025-12-07
- Fix postprocessing issues with SSAO and outlines for large structures (#1387)
- Reduce automatic quality on standalone HMD devices
## [v5.4.1] - 2025-11-16
- Fix ugly camera clipping in snapshot transitions
- Add viewport button to toggle illumination mode
- Fix bounding sphere computation for 3D text
- Structure bounding sphere includes atom VDW radii / coarse sphere radii
- Relax camera limits to allow focusing any selection with >1 atom
- MolViewSpec
- Fix `appendSnapshots` when loading MVSX
- Fix all-selector color not applying on substructure
- Fix primitives in root not being transformed with reference structure
- Color themes do not prefer smoothing (improves performance in animations)
- Allow canvas background interpolation
- Fix `direct-volume` not drawn in illumination mode
- Fix default trackball animated spin speed
- Use `PluginCommands` to set canvas3d props in camera behavior
- Volume improvements
- Add `Volume.periodicity`
- Wrap isosurfaces for periodic volumes
- Fix dimensions for slices
- Add support for Input Method Editor (IME) to text params input
- Update `guessCifVariant` to detect density files not generated by the VolumeServer
## [v5.3.0] - 2025-11-05
- Update loading message in MVS Stories Viewer
- Add `Canvas3D.setAttribs`
- Fix `normalizeWheel` "spin" calculation fallback
- MolViewSpec
- Add support for "topology" formats (TOP, PRMTOP, PSF)
- Add support for additional "coordiates" formats (NCTRAJ, DCD, TRR)
- Fix coarse structure selection
- Fix missing default param values in `primitives_from_uri`
## [v5.2.0] - 2025-10-31
- Handle transparency updates on ImagePass
- Fix CIF parser edge case when the last token is escaped
- MolViewSpec
- Fix tooltips persisting across snapshots
- Fix CIF annotations with no selector columns being ignored
- Fix trackpad lock when camera up parallel to direction
- Add clipping support for primitives
- Support near camera distance
## [v5.1.2] - 2025-10-25
- Fix createColorScaleByType when offsets are available
- Get bond orders from non-standard CONECT records in PDB files
- Remove outdated `gl_FrontFacing` workaround for buggy drivers
- Fix clip objects for direct-volume rendering
- Support "magic window" style AR (via WebXR)
- Fix `PluginState.getStateTransitionFrameIndex`
- Update `GlycamSaccharideNames` and `Monosaccharides` in `carbohydrates/constants.ts`
- Support custom ref resolvers in `State`
- Add full-screen mode support to layout manager
- Add `show-toggle-fullscreen` URL param option to Viewer app
- MolViewSpec
- Support accessing Mol* State nodes by MVS-provided ref
- Add support for DX map format
- Better support for coarse structures in MVS:
- Support for MVS annotations on coarse structures (color_from_*, tooltip_from_*)
- Support for MVS labels on coarse structures (label, label_from_*)
- (Other things already worked on coarse structures before: tooltip, color,component, primitives, component_from_*, primitives_from_*)
- Tidy up MVS builder:
- Add `sphere` and `angle` methods
- [Breaking] Rename builder method primitives_from_uri -> primitivesFromUri
## [v5.0.0] - 2025-09-28
- [Breaking] Renamed some color schemes ('inferno' -> 'inferno-no-black', 'magma' -> 'magma-no-black', 'turbo' -> 'turbo-no-black', 'rainbow' -> 'simple-rainbow')
- [Breaking] `Box3D.nearestIntersectionWithRay` -> `Ray3D.intersectBox3D`
- [Breaking] `Plane3D.distanceToSpher3D` -> `distanceToSphere3D` (fix spelling)
- [Breaking] fix typo `MarchinCubes` -> `MarchingCubes`
- [Breaking] `PluginContext.initViewer/initContainer/mount` are now async and have been renamed to include `Async` postfix
- [Breaking] Add `Volume.instances` support and a `VolumeInstances` transform to dynamically assign it
- This change is breaking because all volume objects require the `instances` field now.
- [Breaking] `Canvas3D.identify` now expects `Vec2` or `Ray3D`
- [Breaking] `TrackballControlsParams.animate.spin.speed` now means "Number of rotations per second" instead of "radians per second"
- [Breaking] `PluginStateSnapshotManager.play` now accepts an options object instead of a single boolean value
- Update production build to use `esbuild`
- Emit explicit paths in `import`s in `lib/`
- Fix outlines on opaque elements using illumination mode
- Change `Representation.Empty` to a lazy property to avoid issue with some bundlers
- MolViewSpec extension:
- Generic color schemes (`palette` parameter for color_from_* nodes)
- Annotation field remapping (`field_remapping` parameter for color_from_* nodes)
- `representation` node: support custom property `molstar_representation_params`
- Add `backbone` and `line` representation types
- `primitives` node: support custom property `molstar_mesh/label/line_params`
- `canvas` node: support custom property `molstar_postprocessing` with the ability to customize outline, depth of field, bloom, shadow, occlusion (SSAO), fog, and background
- `clip` node support for structure and volume representations
- `grid_slice` representation support for volumes
- Support tethers and background for primitive labels
- Support `snapshot_key` parameter on primitives that enables transition between states via clicking on 3D objects
- Inline selectors and MVS annotations support `instance_id`
- Support `matrix` on transform params
- Support `surface_type` (`molecular` / `gaussian`) on for `surface` representation nodes
- Add `instance` node type
- Add `transform.rotation_center` property that enables rotating an object around its centroid or a specific point
- Support transforming and instancing of structures, components, and volumes
- Use params hash for node version for more performant tree diffs
- Add `Snapshot.animation` support that enables animating almost every property in a given tree
- Add `createMVSX` helper function
- Support Mol* trackball animation via `animation.custom.molstar_trackball`
- MVSX - use Murmur hash instead of FNV in archive URI
- Support additional file formats (pdbqt, gro, xyz, mol, sdf, mol2, xtc, lammpstrj)
- Support loading trajectory coordinates from separate nodes
- Trigger markdown commands from primitives using `molstar_markdown_commands` custom extensions
- Support `molstar_on_load_markdown_commands` custom state on the `root` node
- Print tree validation errors to plugin log
- Added new color schemes, synchronized with D3.js ('inferno', 'magma', 'turbo', 'rainbow', 'sinebow', 'warm', 'cool', 'cubehelix-default', 'category-10', 'observable-10', 'tableau-10')
- Snapshot Markdown improvements
- Add `MarkdownExtensionManager` (`PluginContext.managers.markdownExtensions`)
- Support custom markdown commands to control the plugin via the `[link](!command)` pattern
- Support rendering custom elements via the `![alt](!parameters)` pattern
- Support tables
- Support loading images and audio from MVSX files
- Indicate external links with ⤴
- Audio support
- Add `PluginState.Snapshot.onLoadMarkdownCommands`
- Avoid calculating rings for coarse-grained structures
- Fix isosurface compute shader normals when transformation matrix is applied to volume
- Symmetry operator naming for spacegroup symmetry - parenthesize multi-character indices (1_111-1 -> 1_(11)1(-1))
- Add `SymmetryOperator.instanceId` that corresponds to a canonical operator name (e.g. ASM-1, ASM-X0-1 for assemblies, 1_555, 1_(11)1(-1) for crystals)
- Mol2 Reader
- Fix column count parsing
- Add support for substructure
- Fix shader error when clipping flags are set without clip objects present
- Fix wrong group count calculation on geometry update (#1562)
- Fix wrong instance index in `calcMeshColorSmoothing`
- Add `Ray3D` object and helpers
- Volume slice representation: add `relativeX/Y/Z` options for dimension
- Add `StructureInstances` transform
- `mvs-stories` app
- Add `story-id` URL arg support
- Add `story-session-url` URL arg support
- Add "Download MVS State" link
- Add "Open in Mol*" link
- Add "Edit in MolViewStories" link for story states
- Add ray-based picking
- Render narrow view of scene scene from ray origin & direction to a few pixel sized viewport
- Cast ray on every input as opposed to the standard "whole screen" picking
- Can be enabled with new `Canvas3dInteractionHelperParams.convertCoordsToRay` param
- Allows to have input methods that are 3D pointers in the scene
- Add `ray: Ray3D` property to `DragInput`, `ClickInput`, and `MoveInput`
- Add async, non-blocking picking (only WebGL2)
- Refactor `Canvas3dInteractionHelper` internals to use async picking for move events
- Add `enable` param for post-processing effects. If false, no effects are applied.
- Dot volume representation improvements
- Add positional perturbation to avoid camera artifacts
- Fix handling of negative isoValues by considering only volume cells with values lower than isoValue (#1559)
- Fix volume-value size theme
- Change the parsing of residue names in PDB files from 3-letter to 4-letter.
- Support versioning transform using a hash function in `mol-state`
- Support for "state snapshot transitions"
- Add `PluginState.Snapshot.transition` that enables associating a state snapshot with a list states that can be animated
- Add `AnimateStateSnapshotTransition` animation
- Update the snapshots UI to support this feature
- Use "proper time" in the animation loop to prevent animation skips during blocking operations (e.g., shader complication)
- Add `Hsl` and (normalized) `Rgb` color spaces
- Add `Color.interpolateHsl`
- Add `rotationCenter` property to `TransformParam`
- Add Monolayer transparency (exploiting dpoit).
- Add plugin config item ShowReset (shows/hides "Reset Zoom" button)
- Fix transform params not being normalized when used together with param hash version
- Replace `immer` with `mutative`
- Fix renderer transparency check
- Add outlines improvements
- VolumeServer & "VolumeCIF": default to P 1 spacegroup
- Fix `ColorScale` for continuous case without offsets (broke in v4.13.0)
- Experimental: support for custom color themes in Sequence Panel
- Switch files.rcsb.org validation report URL to new endpoint /validation/view
- Improve picking of objects with too many groups, pick whole instance/object
- Add WebXR support
- Requires immersive AR/VR headset
- Supplements non-XR: enter/exit XR anytime and see (mostly) the same scene
- Add `Canvas3D.xr` for managing XR sessions
- Add `PointerHelper` for rendering XR input devices
- Add XR button to Viewer and Mesoscale Explorer
- Add XR button to render-structure in tests/browser
- Fix illumination denoising with transparency on transparent background
- Change the `to_mmCIF` function parameter from `structure` to `structures` to support either a single structure or an array of structures
- ModelServer and VolumeServer: add configurable robots.txt
- Adaptive parallel shader compilation
- Split shader compilation into linking and finalizing
- Start linking as early as possible and wait with finalizing to avoid blocking main thread
- Use of `KHR_parallel_shader_compile` extension when available to check status
- Add `ShaderManager` to compile shaders based on `Canvas3D` params and `Scene` content
- Draw `Scene` only when shaders are ready
- Fix incorrect animation loop handling in the screenshot code
## [v4.18.0] - 2025-06-08
- MolViewSpec extension:
- Support for label_comp_id and auth_comp_id in annotations
- Geometric primitives - do not render if position refers to empty substructure
- Primitive arrow - nicer default cap size (relative to tube_radius)
- Primitive angle_measurement - added vector_radius param
- Fix MVSX file assets being disposed in multi-snapshot states
- Add `mol-utils/camera.ts` with `fovAdjustedPosition` and `fovNormalizedCameraPosition`
- Show FOV normalized position in `CameraInfo` UI and use it in "Copy MVS State"
- Support static resources in `AssetManager`
- General:
- Use `isolatedModules` tsconfig flag
- Fix TurboPack build when using ES6 modules
- Support `pickingAlphaThreshold` when `xrayShaded` is enabled
- Support sampling from arbitrary planes for structure plane and volume slice representations
- Refactor SCSS to not use `@import` (fixes deprecation warnings)
## [v4.17.0] - 2025-05-22
- Remove `xhr2` dependency for NodeJS, use `fetch`
- Add `mvs-stories` app included in the `molstar` NPM package
- Use the app in the corresponding example
- Interactions extension: remove `salt-bridge` interaction kind (since `ionic` is supported too)
## [v4.16.0] - 2025-05-20
- Load potentially big text files as `StringLike` to bypass string size limit
- MolViewSpec extension:
- Load single-state MVS as if it were multi-state with one state
- Merged `loadMVS` options `keepCamera` and `keepSnapshotCamera` -> `keepCamera`
- Removed `loadMVS` option `replaceExisting` (is now default)
- Added `loadMVS` option `appendSnapshots`
- Fix camera not being interpolated in MP4 export due to updates in WebGL ContextLost handling
## [v4.15.0] - 2025-05-19
- IHM improvements:
- Disable volume streaming
- Disable validation report visualization
- Enable assembly symmetry for integrative models
- Fix transparency rendering with occlusion in NodeJS
- mmCIF Support
- Add custom `molstar_bond_site` category that enables serializing explicit bonds by referencing `atom_site.id`
- Add `includeCategoryNames`, `keepAtomSiteId`, `exportExplicitBonds`, `encoder` properties to `to_mmCIF` exporter
- Add support for attachment points property (`M APO`) to the MOL V2000 parser
- Add `json-cif` extension that should pave way towards structure editing capabilities in Mol\*
- JSON-based encoding of the CIF data format
- `JSONCifLigandGraph` that enables editing of small molecules via modifying `atom_site` and `molstar_bond_site` categories
- Add `ligand-editor` example that showcases possible use-cases of the `json-cif` extension
- Breaking (minor): Changed `atom_site.id` indexing to 1-based in `mol-model-formats/structure/mol.ts::getMolModels`.
- WebGL ContextLost handling
- Fix missing framebuffer & drawbuffer re-attachments
- Fix missing cube texture re-initialization
- Fix missing extensions reset
- Fix timer clearing edge case
- Add reset support for geometry generated on the GPU
## [v4.14.1] - 2025-05-09
- Do not raise error when creating duplicate state transformers and print console warning instead
## [v4.14.0] - 2025-05-07
- Fix `Viewer.loadTrajectory` when loading a topology file
- Fix `StructConn.residueCantorPairs` to not include identity pairs
- Add format selection option to image export UI (PNG, WebP, JPEG)
- Add `StateBuilder.To.updateState`
- MVS:
- Support updating transform states
- Add support for `is_hidden` custom state as an extension
- Add `queryMVSRef` and `createMVSRefMap` utility functions
- Adjust max resolution of surfaces for auto quality (#1501)
- Fix switching representation type in Volume UI
- VolumeServer: Avoid grid expansion when requiring unit cell (avoids including an extra layer of cells outside the unit cell query box)
## [v4.13.0] - 2025-04-14
- Support `--host` option for build-dev.mjs script
- Add `Viewer.loadFiles` to open supported files
- Support installing the viewer as a Progressive Web App (PWA)
- `ihm-restraints` example: show entity labels
- Fix `element-point` visual not using child unit
- Ignore `renderables` with empty draw count
- Add experimental support for `esbuild` for development
- Use `npm run dev` for faster development builds
- Use `StructureElement.Bundle` instead of expressions to serialize measurement elements
- Fixes measurements not being supported for coarse models
- Implementation of `ColorScale.createDiscrete` (#1458)
- Add `ColorScale.createDiscrete` to the `uncertainty` color theme
- Fix color palette shown in the UI (for non-gradient palettes)
- Fix colors description in the UI (when using custom thresholds)
- Fix an edge case in the UI when the user deletes all colors from the color list
- Add `interactions` extension and a corresponding example that utilizes it
- Add element source index to default atomic granularity hover labels
- Add `StructureElement.Schema` based on corresponding MolViewSpec implementation that allows data-driven selection of structural elements
- Add `StructureElement.Loci/Bundle.fromExpression/Query/Schema` helper functions
- Add `addLinkCylinderMesh` (from `createLinkCylinderMesh`)
- Add `Unit.transientCache` and `Unit.getCopy`
- Fix `ElementBondIterator` indices mapping logic for inter-unit bonds
- Fix `pickPadding` and `pickScale` not updating `PickHelper`
- MolViewSpec extension: support loading extensions when loading multistate files
- Do not add bonds for pairs of residues that have a `struct_conn` entry
- Improved `ma_qa_metric` support
- Parse all local metrics
- Ability to select alternate metrics in the pLDDT/qmean themes
- Do not assume PAE plot is symmetric
- Added `PluginConfig.Viewport.ShowScreenshotControls` to control visibility of screenshot controls
- Fix MolViewSpec builder for volumes.
- Generalize `mvs-kinase-story` example to `mvs-stories`
- Add TATA-binding protein story
- Improve the Kinase story
- Fix alpha orbitals example
## [v4.12.0] - 2025-02-28
- Fix PDBj structure data URL
- Improve logic when to cull in renderer
- Add `atom.ihm.has-seq-id` and `atom.ihm.overlaps-seq-id-range` symbol to the query language
- MolViewSpec extension:
- Add box, arrow, ellipse, ellipsoid, angle primitives
- Add basic support for volumetric data (map, Volume Server)
- Add support for `molstar_color_theme_name` custom extension
- Better IH/M support:
- Support `coarse` components
- Support `spacefill` representation
- Support `carbohydrate` representation
- Support for `custom.molstar_use_default_coloring` property on Color node.
- Use `atom.ihm.has-seq-id` and `atom.ihm.overlaps-seq-id-range` for matching `label_seq_id` locations to support querying coarse elements.
- Add ihm-restraints example
- Add `mvs-kinase-story` example
- Remove static uses of `ColorTheme` and `SizeTheme` fields. Should resolvent "undefined" errors in certain builds
- Add `transform` property to clip objects
- Add support for trimming `image` geometry to a box
- Improve/fix iso-level support of `slice` representation
- Add support for rotating `slice` representation around an axis
- Add default color support for palette based themes
- Add `plane` structure representation
- Can be colored with any structure theme
- Can be colored with the `external-volume` theme
- Can show atoms as a cutout
- Supports principal axes and bounding box as a reference frame
- Add `Camera` section to "Screenshot / State" controls
- Add `CoarseIndex` for fast lookup of coarse elements
## [v4.11.0] - 2025-01-26
- Fix for tubular helices issue (Fixes #1422)
- Volume UI improvements
- Render all volume entries instead of selecting them one-by-one
- Toggle visibility of all volumes
- More accessible iso value control
- Render all volume entries instead of selecting them one-by-one
- Toggle visibility of all volumes
- More accessible iso value control
- Support wheel event on sliders
- MolViewSpec extension:
- Add validation for discriminated union params
- Primitives: remove triangle_colors, line_colors, have implicit grouping instead; rename many parameters
- Add validation for discriminated union params
- Primitives: remove triangle_colors, line_colors, have implicit grouping instead; rename many parameters
- UI configuration options
- Support removal of independent selection controls in the viewport
- Support custom selection controls
- Support for custom granularity dropdown options
- Support for custom Sequence Viewer mode options
- Add `external-structure` theme that colors any geometry by structure properties
- Support float and half-float data type for direct-volume rendering and GPU isosurface extraction
- Minor documentation updates
- Add support for position-location to `volume-value` color theme
- Add support for color themes to `slice` representation
- Improve/fix palette support in volume color themes
- Fix `Plane3D.projectPoint`
- Fix marking related `image` rendering issues
- Handle pixels without a group
- Take fog into account
- MolViewSpec extension: Initial support for customizable representation parameters
- Quick Styles section reorganized
- UI color improvements (scrollbar contrast, toggle button hover color)
- Add `overrideWater` param for entity-id color theme
- Renames PDB-Dev to PDB-IHM and adjusts data source
- Fix vertex based themes for spheres shader
- Add volume dot representation
- Add volume-value size theme
- Sequence panel: Mark focused loci (bold+underline)
- Change modifier key behavior in Normal Mode (default = select only, Ctrl/Cmd = add to selection, Shift = extend last selected range)
- Handle Firefox's limit on vertex ids per draw (#1116)
- Fix behavior of `Vec3.makeRotation(out, a, b)` when `a ≈ -b`
## [v4.10.0] - 2024-12-15
@@ -83,7 +614,7 @@ Note that since we don't clearly distinguish between a public and private interf
- Fix `findPredecessorIndex` bug when repeating values
- MolViewSpec: Support for transparency and custom properties
- MolViewSpec: MVP Support for geometrical primitives (mesh, lines, line, label, distance measurement)
- Mesoscale Explorer: Add support for 4-character PDB IDs (e.g., 8ZZC) in PDB-Dev loader
- Mesoscale Explorer: Add support for 4-character PDB IDs (e.g., 8ZZC) in PDB-IHM/PDB-Dev loader
- Fix Sequence View in Safari 18
- Improve performance of `IndexPairBonds` assignment when operator keys are available
- ModelArchive QualityAssessment extension:
@@ -136,7 +667,7 @@ Note that since we don't clearly distinguish between a public and private interf
- Improve entity-id coloring for structures with multiple models from the same source (#1221)
- Wrap screenshot & image generation in a `Task`
- AlphaFold DB: Add BinaryCIF support when fetching data
- PDB-Dev: Add support for 4-character PDB IDs (e.g., 8ZZC)
- PDB-IHM/PDB-Dev: Add support for 4-character PDB IDs (e.g., 8ZZC)
- Fix polymer-gap visual coloring with cartoon theme
- Add formal-charge color theme (#328)
- Add more coloring options to cartoon theme

View File

@@ -84,7 +84,16 @@ Wipes the `build` and `lib` directories and `.tsbuildinfo` files.
Runs the cleanup script prior to building the project, forcing a full rebuild of the project.
Use these commands to resolve occassional build failures which may arise after some dependency updates. Once done, `npm run build` should work again. Note that full rebuilds take more time to complete.
Use these commands to resolve occasional build failures which may arise after some dependency updates. Once done, `npm run build` should work again. Note that full rebuilds take more time to complete.
### Develop with `esbuild`
Experimental support for faster builds with `esbuild`
- `npm run dev:all` - watch mode for all apps and examples
- `npm run dev:viewer` - watch mode for viewer
- `npm run dev:apps` - watch mode for all apps
- `npm run dev:examples` - watch mode for all examples
- `npm run dev -- -a <app name 1> <app name 2> -e <example name 1> ...` - watch mode for specified apps/examples. `-a`/`-e` with without any names will build everything.
### Build for production:
NODE_ENV=production npm run build
@@ -103,7 +112,6 @@ From the root of the project:
and navigate to `build/viewer`
### Code generation
**CIF schemas**
@@ -118,16 +126,16 @@ and navigate to `build/viewer`
**Ion names**
node --max-old-space-size=4096 lib/commonjs/cli/chem-comp-dict/create-ions.js src/mol-model/structure/model/types/ions.ts
node --max-old-space-size=8192 lib/commonjs/cli/chem-comp-dict/create-ions.js src/mol-model/structure/model/types/ions.ts
**Saccharide names**
node --max-old-space-size=4096 lib/commonjs/cli/chem-comp-dict/create-saccharides.js src/mol-model/structure/model/types/saccharides.ts
node --max-old-space-size=8192 lib/commonjs/cli/chem-comp-dict/create-saccharides.js src/mol-model/structure/model/types/saccharides.ts
### Other scripts
**Create chem comp bond table**
node --max-old-space-size=4096 lib/commonjs/cli/chem-comp-dict/create-table.js build/data/ccb.bcif -b
node --max-old-space-size=8192 lib/commonjs/cli/chem-comp-dict/create-table.js build/data/ccb.bcif -b
**Test model server**
@@ -182,9 +190,14 @@ To get syntax highlighting for shader files add the following to Visual Code's s
npm publish
## Deploy
To prepare apps and demos for https://molstar.org deploy, run:
npm run test
npm run build
node ./scripts/deploy.js # currently updates the viewer on molstar.org/viewer
npm run deploy:local
To commit these changes remotely to the `molstar/molstar.github.io` repo:
npm run deploy:remote
## Contributing
Just open an issue or make a pull request. All contributions are welcome.

1
breaking-v6-changes.md Normal file
View File

@@ -0,0 +1 @@
- Remove `checkeredCanvasBackground` from `PluginContext` and `PluginContainer`

View File

@@ -14,6 +14,7 @@ chemical.melting_point
chemical_formula.moiety
chemical_formula.sum
chemical_formula.iupac
chemical_formula.weight
atom_type.symbol
@@ -25,6 +26,8 @@ atom_type_scat.source
space_group.crystal_system
space_group.name_h-m_full
space_group.name_h-m_alt
space_group.name_hall
space_group.it_number
space_group_symop.operation_xyz
1 audit.block_doi
14 chemical_formula.weight chemical_formula.iupac
15 atom_type.symbol chemical_formula.weight
16 atom_type.description atom_type.symbol
17 atom_type.description
18 atom_type_scat.dispersion_real
19 atom_type_scat.dispersion_imag
20 atom_type_scat.source
26 cell.length_b space_group_symop.operation_xyz
27 cell.length_c cell.length_a
28 cell.angle_alpha cell.length_b
29 cell.length_c
30 cell.angle_alpha
31 cell.angle_beta
32 cell.angle_gamma
33 cell.volume

15
data/pwa/README.md Normal file
View File

@@ -0,0 +1,15 @@
The files in this directory are used for deploying the Mol* Viewer as a PWA (Progressive Web App) at https://molstar.org/viewer/. They may serve as an example for creating your own PWA but wont work as-is. See `/script/deploy.js` for where these files are copied and how they are transformed during deployment.
## PWA features
- The Service Worker will cache static resources so the Viewer can be used without internet access. This works without installing, i.e., also in Firefox.
- Once installed, file types listed in the Manifest can be opened from, e.g., the Windows File Explorer.
## Notes for development
In Chrome you can see a list of installed PWAs at chrome://apps/. A right-click opens a menu with an option uninstall.
The Chrome Dev Tools have a section 'Application' to inspect and manage PWA aspects like the Manifest and Service Workers.

BIN
data/pwa/logo-144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,39 @@
{
"id": "https://molstar.org/viewer/",
"name": "Mol* Viewer",
"short_name": "Mol*",
"description": "Mol* Viewer: a modern web app for 3D visualization and analysis of large biomolecular structures.",
"start_url": "./index.html",
"theme_color": "#eeece7",
"background_color": "#eeece7",
"display": "standalone",
"icons": [
{
"src": "favicon.ico",
"sizes": "48x48"
},
{
"src": "logo-144.png",
"sizes": "144x144"
}
],
"file_handlers": [
{
"action": "./index.html",
"accept": {
"application/vnd.molstar": [".molx", ".molj"],
"text/plain": [
".mol", ".mol2", ".sdf", ".sd", ".pdb", ".ent", ".pdbqt", ".cif", ".mcif", ".mmcif", ".xyz", ".gro", ".lammpstrj",
".cub", ".cube", ".dx"
],
"application/octet-stream": [
".bcif",
".dxbin", ".ccp4", ".mrc", ".map", ".dsn6", ".brix"
]
}
}
],
"launch_handler": {
"client_mode": ["auto"]
}
}

44
data/pwa/pwa.js Normal file
View File

@@ -0,0 +1,44 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Andy Turner <agdturner@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
window.addEventListener('molstarViewerCreated', e => {
const viewer = e.detail.viewer;
// Handle incoming files
if ('launchQueue' in window) {
launchQueue.setConsumer((launchParams) => {
if (!launchParams.files.length) return;
const files = [];
for (const fileHandle of launchParams.files) {
files.push(fileHandle.getFile());
}
Promise.all(files).then((files) => {
viewer.loadFiles(files);
});
});
}
});
// Register Progressive Web App service worker.
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('./sw.js')
.then(function (registration) {
// Registration was successful
if (molstar.isDebugMode) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}
}, function (err) {
// registration failed :(
if (molstar.isDebugMode) {
console.error('ServiceWorker registration failed: ', err);
}
});
});
}

60
data/pwa/sw.js Normal file
View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Andy Turner <agdturner@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
/** version from package.json, to be filled in during deployment */
const VERSION = '__MOLSTAR_VERSION__';
const CACHE_NAME = `molstar-viewer-${VERSION}`;
// The static resources that the app needs to function.
const APP_STATIC_RESOURCES = [
'favicon.ico',
'index.html',
'molstar.css',
'molstar.js',
'manifest.webmanifest',
'logo-144.png',
'pwa.js'
];
async function cacheStaticResources() {
const cache = await caches.open(CACHE_NAME);
await cache.addAll(APP_STATIC_RESOURCES);
await self.skipWaiting(); // Ensures the new service worker takes control immediately.
}
async function deleteOldCaches() {
const keys = await caches.keys();
await Promise.all(
keys.map((key) => {
if (key !== CACHE_NAME) {
return caches.delete(key);
}
}),
);
await self.clients.claim(); // Ensures the new service worker takes control immediately.
}
async function respondWithCacheFirst(request) {
// Try to match the request with the cache
const cachedResponse = await caches.match(request);
return cachedResponse || fetch(request);
}
self.addEventListener('install', (event) => {
// console.log(`Service Worker version ${VERSION} installed.`);
event.waitUntil(cacheStaticResources());
});
self.addEventListener('activate', (event) => {
// console.log(`Service Worker version ${VERSION} activated.`);
event.waitUntil(deleteOldCaches());
});
self.addEventListener('fetch', (event) => {
event.respondWith(respondWithCacheFirst(event.request));
});

View File

@@ -24,7 +24,7 @@ npm install
Afterwards, build the project source:
```
npm run build-tsc
npm run build:lib
```
and run the server by

View File

@@ -0,0 +1,4 @@
# Interactions extension
The Interactions extension enables computing or providing custom interactions between multiple selections/structures.
For usage, see the [example source code](https://github.com/molstar/molstar/tree/master/src/examples/interactions).

View File

@@ -94,7 +94,7 @@ The extension uses several transformations to process and visualize tunnel data:
To help users understand how to use these transformations in practice, include detailed examples:
### Visualizing Multiple Tunnels
This example ([runVisualizeTunnels](../../../src/extensions/sb-ncbr/tunnels/examples.ts#L19)) demonstrates how to visualize multiple tunnels from a fetched dataset.
This example (see `src/extensions/sb-ncbr/tunnels/examples.ts#L19`) demonstrates how to visualize multiple tunnels from a fetched dataset.
```typescript
update.toRoot()
.apply(TunnelsFromRawData, { data: tunnels })
@@ -104,7 +104,7 @@ update.toRoot()
```
### Visualizing a Single Tunnel
This example ([runVisualizeTunnel](../../../src/extensions/sb-ncbr/tunnels/examples.ts#L46)) shows how to visualize a single tunnel.
This example (see `src/extensions/sb-ncbr/tunnels/examples.ts#L46`) shows how to visualize a single tunnel.
```typescript
update.toRoot()
.apply(TunnelFromRawData, {

View File

@@ -25,7 +25,7 @@ import { PluginContext } from 'molstar/lib/mol-plugin/context';
git clone https://github.com/molstar/molstar.git
cd molstar
npm install
npm build
npm run build
```
--------------------
@@ -33,11 +33,11 @@ npm build
For a watch task to automatically rebuild the source code on changes, run
```
npm run watch
npm run dev
```
or if working just with the Viewer app for better performance
```
npm run watch-viewer
npm run dev:viewer
```

View File

@@ -48,4 +48,7 @@
* CLR (e.g. 3GKI) - four fused rings
* Assembly symmetries
* 5M30 (Assembly 1, C3 local and pseudo)
* 1RB8 (Assembly 1, I global)
* 1RB8 (Assembly 1, I global)
* Deuterium atoms
* 3CWH (XUL with D and DOD)
* 8TT8 (HOH and other with D)

View File

@@ -1,6 +1,6 @@
# Building a Custom Library
This page goes over creating a custom Mol\* based library usable inside a `<script>` tag in an HTML page.
This page goes over creating a custom Mol\* based library usable inside a `<script>` tag in an HTML page using the `esbuild` tool.
## Setup
@@ -141,7 +141,7 @@ export async function loadStructure(plugin: PluginUIContext, url: string, option
```
- Create `src/style.scss`:
```scss
@import '../node_modules/molstar/lib/mol-plugin-ui/skin/light.scss';
@use '../node_modules/molstar/lib/mol-plugin-ui/skin/light.scss';
```
- Create `build/ui.html`:
```html

View File

@@ -15,10 +15,33 @@ There are 4 basic ways of instantiating the Mol* plugin.
## ``Viewer`` wrapper
- The most basic usage is to use the ``Viewer`` wrapper. This is best suited for use cases that do not require much custom behavior and are mostly about just displaying a structure.
- See ``Viewer`` class is defined in [src/apps/viewer/app.ts](https://github.com/molstar/molstar/blob/master/src/apps/viewer/app.ts) for available methods and options.
- The most basic usage is to use the ``Viewer`` wrapper. This is best suited for use cases that do not require custom behavior and are mostly about just displaying a structure.
- See ``Viewer`` class is defined in [src/apps/viewer/app.ts](https://github.com/molstar/molstar/blob/master/src/apps/viewer/app.ts) for available methods
- See [options.ts](https://github.com/molstar/molstar/blob/master/src/apps/viewer/options.ts) for available plugin options
- See [embedded.html](https://github.com/molstar/molstar/blob/master/src/apps/viewer/embedded.html) and [mvs.html](https://github.com/molstar/molstar/blob/master/src/apps/viewer/mvs.html) for example usage
- Importing `molstar.js` will expose `molstar.lib` namespace that allow accessing various functionality without a bundler such as WebPack or esbuild. See the `mvs` example above for basic usage.
- Alternative color themes can be used by importing `theme/dark.css` (or `light/blue`) instead of `molstar.css`
Example usage without using WebPack:
### molstar.js and molstar.css sources
- Download `molstar` NPM package and use the files from `build/viewer` diractory
- Use `jsdelivr` CDN
- `<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/molstar@latest/build/viewer/molstar.js" />`
- `<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/molstar@latest/build/viewer/molstar.css" />`
- `@latest` can be replaced by a specific Mol* version, e.g., `@5.4.2`
- Clone & build the GitHub repository
- This option allows for quite straightforward extension customization, e.g., not including movie export, which reduces the bundle size by ~0.5MB
### Bundle size
By default, the `Viewer` includes all the available extensions. This increases the bundle size significantly, especially by including the `mp4-export`, which is responsible for almost `0.5MB` of compressed bundle size.
It is quite easy to reduce this bundle size by cloning the Mol\* repository, editing [extensions.ts](https://github.com/molstar/molstar/blob/master/src/apps/viewer/options.ts) and rebuilding it with `npm run build:apps`. The new build will be available
in the `build/viewer` directory (the JS file you will find there is uncompressed, but your hosting setup should include automatic gzip compression, significantly reducing the size).
Alternatively, you can explore building your own "viewer" using the base Mol\* library. For this, see the options below.
### Example
```HTML
<style>
@@ -35,7 +58,7 @@ Example usage without using WebPack:
- the folder build/viewer after cloning and building the molstar package
- from the build/viewer folder in the Mol* NPM package
-->
<link rel="stylesheet" type="text/css" href="molstar.css" />
<link rel="stylesheet" type="text/css" href="./molstar.css" />
<script type="text/javascript" src="./molstar.js"></script>
<div id="app"></div>
@@ -62,13 +85,15 @@ Example usage without using WebPack:
</script>
```
When using WebPack (or possibly other build tool) with the Mol* NPM package installed, the viewer class can be imported using
### Using WebPack/esbuild/...
When using WebPack (or other bundler) with the Mol* NPM package installed, the viewer class can be imported using
```ts
import { Viewer } from 'molstar/build/viewer/molstar'
import { Viewer } from 'molstar/lib/apps/viewer/app'
function initViewer(target: string | HTMLElement) {
return new Viewer(target, { /* options */})
return Viewer.create(target, { /* options */}) // returns a Promise
}
```
@@ -139,6 +164,8 @@ export function MolStarWrapper() {
// In debug mode of react's strict mode, this code will
// be called twice in a row, which might result in unexpected behavior.
useEffect(() => {
// By default, react will call each useEffect twice if using Strict mode in
// debug build, it is recommended to disable strict mode for this reason if possible
async function init() {
window.molstar = await createPluginUI({
target: parent.current as HTMLDivElement,
@@ -247,7 +274,7 @@ async function init() {
const canvas = <HTMLCanvasElement> document.getElementById('molstar-canvas');
const parent = <HTMLDivElement> document.getElementById('molstar-parent');
if (!plugin.initViewer(canvas, parent)) {
if (!(await plugin.initViewerAsync(canvas, parent))) {
console.error('Failed to init Mol*');
return;
}

View File

@@ -0,0 +1,107 @@
# Markdown Extension Manager
The `markdownExtensions` manager in `PluginContext.manager` allows customizing
the `Markdown` React component to enable executing commands and rendering custom content.
The main use case of this is enriching [MolViewSpec](`https://molstar.org/mol-view-spec`) support.
## API
- `PluginContext.manager.markdownExtensions.register*` functions can be used to register extensions and state/data resolvers to make the the manager work with plugin extension
- `PluginContext.manager.markdownExtensions.remove*` can be used to dynamically remove the above
## Commands
Extends Markdown Hyperlink syntax to support expressions of the form `[title](!c1=v1&c2=v2&...)` into an executable command. The command can be executed either on click, mouse enter, or mouse leave.
Generally, the command should be URL encoded, e.g., `a b` => `a%20b` (in JS, `encodeURIComponent`, in Python `urllib.parse.quote_plus/urlencode`).
### Built-in Commands
- `center-camera` - Centers the camera
- `apply-snapshot=key` - Loads snapshots with the provided key
- `next-snapshot[=-1|1]` - Loads next/previous snapshot, the direction is optional and default to `1`
- `play-snapshots` - Starts playback of state snapshots
- `play-transition` - Plays an animation associated with the given snapshot
- `stop-animation` - Stops currently playing animation
- `focus-refs=ref1,ref2,...` - On click, focuses nodes with the provided refs
- `highlight-refs=ref1,ref2,...` - On mouse over, highlights the provided refs
- `query=...&lang=...&action=highlight,focus&focus-radius=...`
- `query` is an expression (e.g., `resn HEM` when using PyMol syntax)
- (optional) `lang` is one of `mol-script` (default), `pymol`, `vmd`, `jmol`
- (optional) `action` is an array of `highlight` (default), `focus` (multiple actions can be specified)
- (optional) `focus-radius` is extra distance applied when focusing the selection (default is `3`)
- Example: `[HEM](!query=resn%20HEM%26lang=pymol&action=highlight,focus)` highlights or focuses the HEM residue (the query must be URL encoded because it contains spaces and possibly other special characters)
- `play-audio=src`, `toggle-audio[=src]`, `stop-audio`, `pause-audio`, `dispose-audio` - Audio playback support
## Custom Content
Extends Markdown Image syntax to support expressions of the form `![alt](!c1=v1&c2=v2&...)` to render custom elements instead.
### Built-in Custom Content
- `color-swatch=color` - Renders a box with the provided color
- Color palettes:
- `color-palette-name=name` - Renders a gradient with the provided named color palette (see `mol-util/color/lists.ts` for supported color schemes)
- `color-palette-colors=color1,color2` - Renders a gradient with the provided colors
- `color-palette-width=CCS-value` - Specifies the width of the element, defaults to `150px`
- `color-palette-height=CCS-value` - Specified the height of the element, defaults to `0.5em`
- `color-palette-discrete` - Renders discrete color list instead of interpolating
## Example
```markdown
### Highlight/Focus:
- ![blue](!color-swatch=blue) [polymer](!highlight-refs=polymer&focus-refs=polymer)
- ![blue](!color-swatch=red) [ligand](!highlight-refs=ligand&focus-refs=ligand)
- [both](!highlight-refs=polymer,ligand&focus-refs=polymer,ligand)
### Color Palettes
|name|visual|
|---:|---|
|viridis|![viridis](!color-palette-name=viridis)|
|rainbow (discrete)|![simple-rainbow](!color-palette-name=simple-rainbow&color-palette-discrete)|
|custom|![custom](!color-palette-colors=red,#00ff00,rgb(0,0,255))|
### Camera controls
- [center](!center-camera)
### Image embedded in MVSX file
![mvsx image](logo.png)
```
This works with the MolViewSpec state built by:
```py
import molviewspec as mvs
builder = mvs.create_builder()
assets = {
"1cbs.cif": "https://files.wwpdb.org/download/1cbs.cif",
"logo.png": "https://molstar.org/img/molstar-logo.png",
}
model = (
builder.download(url="1cbs.cif")
.parse(format="mmcif")
.model_structure()
)
(
model.component(selector="polymer")
.representation(ref="polymer")
.color(color="blue")
)
(
model.component(selector="ligand")
.representation(ref="ligand")
.color(color="red")
)
mvsx = mvs.MVSX(
data=builder.get_state(
description="""...""" # inline the code above
),
assets=assets
)
```

View File

@@ -1,11 +1,136 @@
# Selections
Assuming you have a model already loaded into the plugin (see [Creating Plugin Instance](./instance.md)), these are some of the following method you can select structural data.
## Basic Concepts
### Selecting directly from the `hierarchy` manager
### Location
One can select a subcomponent's data directly from the plugin manager.
The selection model in Mol\* is based on a generic concept called *location*. A location is a pointer to a selectable element within a scene. For example:
- A structure element location (an atom or a coarse element) is an object composed of `{ structure: Structure, unit: Unit, element: UnitIndex }` (you can think of a `Unit` as a generalized chain)
- A bond location is very similar to structure element, requiring pointers to two units and elements
- A "shape" (generally a mesh) location consists of pointer to the parent shape and a group of triangles
### Loci
Structures and other renderable elements generally consist of many locations and simply using a list of locations would be
prohibitively expensive (e.g., large selections in structures with hundreds of thousands of atoms).
This is why Mol\* introduces
the concept of `Loci` &mdash; a compressed representation of multiple locations. Instead of having a list of structure element locations (`{ structure: Structure, unit: Unit, element: UnitIndex }[]`), the representation becomes (simplified) `{ structure: Structure, unit: Unit, elements: OrderedSet<UnitIndex> }`. The ordered set can be further compressed for continuous ranges, keeping only the index of the 1st and last element.
### Bundle
Locations and loci point to the raw JavaScript data structures representing the underlying molecules, making them not serializable in JSON. A *bundle* is a serializable version of the loci.
### Structure Queries
Defining selections directly using the loci would be very cumbersome. For this reason, Mol\* includes the [MolQl query language](https://molql.org) to help define selections.
## Selection Methods
Assuming you have a model already loaded into the plugin (see [Creating Plugin Instance](./instance.md)), these are some of the methods you can use to create selections.
### MolQL (`mol-script`) language
[MolQL](https://molql.org) (`mol-script`) is a language for addressing crystallographic structures and is a part of the Mol* library found at `https://github.com/molstar/molstar/tree/master/src/mol-script`. It can be used against the Molstar plugin as a query language and transpiled against multiple external molecular visualization libraries(see [here](https://github.com/molstar/molstar/tree/master/src/mol-script/transpilers)).
**Example:** Querying a structure for a specific chain and residue range
Select residues with `12<res_id<200 of chain with auth_asym_id=A`
```typescript
import { compileIdListSelection } from 'molstar/lib/mol-script/util/id-list'
const query = compileIdListSelection('A 12-200', 'auth');
window.molstar?.managers.structure.selection.fromCompiledQuery('add',query);
```
### Selection Queries
Another way to create a selection is via a `SelectionQuery` object. This is a more programmatic way to create a selection. The following example shows how to select a chain and a residue range using a `SelectionQuery` object.
This relies on the concept of `Expression` which is basically a intermediate representation between a Molscript statement and a selection query.
**Example:** Select residues 10-15 of chains A and F in a structure using a `SelectionQuery` object
```typescript
import { MolScriptBuilder as MS, MolScriptBuilder } from 'molstar/lib/mol-script/language/builder';
import { Expression } from 'molstar/lib/mol-script/language/expression';
import { StructureSelectionQuery } from 'molstar/lib/mol-plugin-state/helpers/structure-selection-query'
export function select_multiple() {
const args = [['A', 10, 15], ['F', 10, 15]]
const groups: Expression[] = [];
for (var chain of args) {
groups.push(MS.struct.generator.atomGroups({
'chain-test': MS.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), chain[0]]),
'residue-test': MS.core.rel.inRange([MolScriptBuilder.struct.atomProperty.macromolecular.label_seq_id(), chain[1], chain[2]])
}));
}
var sq = StructureSelectionQuery('residue_range_10_15_in_A_and_F', MS.struct.combinator.merge(groups))
mstar.managers.structure.selection.fromSelectionQuery('set', sq)
}
```
Complex queries can be constructed by combining primitive queries at the level of [`chain-test`, `residue-test`, `entity-test`, etc] (https://github.com/molstar/molstar/blob/6edbae80db340134341631f669eec86543a0f1a8/src/mol-script/language/symbol-table/structure-query.ts#L88C4-L94C112) by combining them via logical connectives provided in the `MolscriptBuilder.core.rel` as above.
Inspect these examples to get a better feeling for this syntax: `https://github.com/molstar/molstar/blob/6edbae80db340134341631f669eec86543a0f1a8/src/mol-plugin-state/helpers/structure-selection-query.ts#L88-L580`
Furthermore, a query made this way can be converted to a `Loci` object which is important in many parts of the libary:
```typescript
// Select residue 124 of chain A and convert to Loci
const Q = MolScriptBuilder;
var sel = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
'chain-test': Q.core.rel.eq([Q.struct.atomProperty.macromolecular.auth_asym_id(), A]),
'residue-test': Q.core.rel.eq([Q.struct.atomProperty.macromolecular.label_seq_id(), 124]),
}), objdata)
let loci = StructureSelection.toLociWithSourceUnits(sel);
```
### Query Functions
Instead of building expressions, query functions can be created directly, e.g.:
```ts
import { atoms } from 'mol-model/structure/query/queries/generators';
const query = atoms({
residueTest: ctx => {
const seqId = StructureProperties.residue.label_seq_id(ctx.element);
return seqId > 10 && seqId < 25;
},
});
const selection = query(new QueryContext(structure));
// ...
```
### Selection Schema
For simple selections, the `StructureElement.Schema` can be used to reference elements within a protein structure using mmCIF `atom_site` field names, e.g.:
```ts
const ala121: StructureElement.Schema = { label_asym_id: 'A', label_seq_id: 121 };
const residues: StructureElement.Schema = {
items: {
auth_asym_id: ['A', 'B'],
auth_seq_id: [10, 11],
}
};
const loci = StructureElement.Loci.fromSchema(structure, residues);
```
Usually, a code editor such as VS Code will auto-suggest all the available field names.
### Using the `hierarchy` manager
It is possible to select a subcomponent's data directly from the plugin manager.
```typescript
import { Structure } from '../mol-model/structure';
@@ -17,7 +142,7 @@ plugin.managers.camera.focusLoci(ligandLoci);
plugin.managers.interactivity.lociSelects.select({ loci: ligandLoci });
```
## Selection callbacks
## Selection Events
If you want to subscribe to selection events (e.g. to change external state in your application based on a user selection), you can use: `plugin.behaviors.interaction.click.subscribe`
Here's an example of passing in a React "set" function to update selected residue positions.
@@ -49,62 +174,17 @@ plugin.behaviors.interaction.click.subscribe(
)
```
### `Molscript` language
## Helper Functions
Molscript is a language for addressing crystallographic structures and is a part of the Mol* library found at `https://github.com/molstar/molstar/tree/master/src/mol-script`. It can be used against the Molstar plugin as a query language and transpiled against multiple external molecular visualization libraries(see [here](https://github.com/molstar/molstar/tree/master/src/mol-script/transpilers)).
Given an `Expression`, `QueryFn`, or `StructureElement.Schema` it is possible to use `fromExpression/Query/Schema` functions on `StructureElement.Loci` and `StructureElement.Bundle`.
### Querying a structure for a specific chain and residue range (select residues with 12<res_id<200 of chain with auth_asym_id==A) :
### `Viewer` app
```typescript
import { compileIdListSelection } from 'molstar/lib/mol-script/util/id-list'
The `Viewer` app provides the `structureInteractivity` function which allows easy selection/highlighting of the loaded structure. For example:
const query = compileIdListSelection('A 12-200', 'auth');
window.molstar?.managers.structure.selection.fromCompiledQuery('add',query);
```
## Selection Queries
Another way to create a selection is via a `SelectionQuery` object. This is a more programmatic way to create a selection. The following example shows how to select a chain and a residue range using a `SelectionQuery` object.
This relies on the concept of `Expression` which is basically a intermediate representation between a Molscript statement and a selection query.
### Select residues 10-15 of chains A and F in a structure using a `SelectionQuery` object:
```typescript
import { MolScriptBuilder as MS, MolScriptBuilder } from 'molstar/lib/mol-script/language/builder';
import { Expression } from 'molstar/lib/mol-script/language/expression';
import { StructureSelectionQuery } from 'molstar/lib/mol-plugin-state/helpers/structure-selection-query'
export function select_multiple() {
const args = [['A', 10, 15], ['F', 10, 15]]
const groups: Expression[] = [];
for (var chain of args) {
groups.push(MS.struct.generator.atomGroups({
"chain-test": MS.core.rel.eq([MolScriptBuilder.struct.atomProperty.macromolecular.auth_asym_id(), chain[0]]),
"residue-test": MS.core.rel.inRange([MolScriptBuilder.struct.atomProperty.macromolecular.label_seq_id(), chain[1], chain[2]])
}));
}
var sq = StructureSelectionQuery('residue_range_10_15_in_A_and_F', MS.struct.combinator.merge(groups))
mstar.managers.structure.selection.fromSelectionQuery('set', sq)
}
```
Complex queries can be constructed by combining primitive queries at the level of [`chain-test`, `residue-test`, `entity-test`, etc] (https://github.com/molstar/molstar/blob/6edbae80db340134341631f669eec86543a0f1a8/src/mol-script/language/symbol-table/structure-query.ts#L88C4-L94C112) by combining them via logical connectives provided in the `MolscriptBuilder.core.rel` as above.
Inspect these examples to get a better feeling for this syntax: `https://github.com/molstar/molstar/blob/6edbae80db340134341631f669eec86543a0f1a8/src/mol-plugin-state/helpers/structure-selection-query.ts#L88-L580`
Furthermore, a query made this way can be converted to a `Loci` object which is important in many parts of the libary:
```typescript
// Select residue 124 of chain A and convert to Loci
const Q = MolScriptBuilder;
var sel = Script.getStructureSelection(Q => Q.struct.generator.atomGroups({
'chain-test' : Q.core.rel.eq([Q.struct.atomProperty.macromolecular.auth_asym_id(), A]),
"residue-test": Q.core.rel.eq([Q.struct.atomProperty.macromolecular.label_seq_id(), 124]),
}), objdata)
let loci = StructureSelection.toLociWithSourceUnits(sel);
```
```ts
viewer.structureInteractivity({
elements: { beg_auth_seq_id: 10, end_auth_seq_id: 50 },
action: 'select',
});
```

View File

@@ -0,0 +1,152 @@
# Structure Superposition
Mol* provides utilities for superposing protein structures, including both sequence-independent (RMSD-based) and structure-based (TM-align) methods.
## RMSD-based Superposition
The basic superposition method uses the Kabsch algorithm to minimize RMSD between corresponding atoms:
```typescript
import { superpose } from 'molstar/lib/mol-model/structure/structure/util/superposition';
import { StructureSelection, QueryContext } from 'molstar/lib/mol-model/structure';
import { compile } from 'molstar/lib/mol-script/runtime/query/compiler';
import { MolScriptBuilder as MS } from 'molstar/lib/mol-script/language/builder';
// Create a query for C-alpha atoms
const caQuery = compile<StructureSelection>(MS.struct.generator.atomGroups({
'atom-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_atom_id(), 'CA'])
}));
// Get selections from two structures
const sel1 = StructureSelection.toLociWithCurrentUnits(caQuery(new QueryContext(structure1)));
const sel2 = StructureSelection.toLociWithCurrentUnits(caQuery(new QueryContext(structure2)));
// Compute superposition (returns transformation matrices)
const transforms = superpose([sel1, sel2]);
// transforms[0].bTransform contains the Mat4 to superpose structure2 onto structure1
```
## TM-align Superposition
TM-align is a structure-based alignment algorithm that produces the TM-score, a length-independent metric for comparing protein structures. Unlike RMSD, TM-score is normalized to [0, 1] and is more robust for comparing proteins of different sizes.
### Basic Usage
```typescript
import { tmAlign } from 'molstar/lib/mol-model/structure/structure/util/tm-align';
import { StructureElement } from 'molstar/lib/mol-model/structure';
// Get C-alpha Loci from two structures (see selection examples above)
const loci1: StructureElement.Loci = /* ... */;
const loci2: StructureElement.Loci = /* ... */;
// Run TM-align
const result = tmAlign(loci1, loci2);
console.log('TM-score (normalized by structure 1):', result.tmScoreA);
console.log('TM-score (normalized by structure 2):', result.tmScoreB);
console.log('RMSD:', result.rmsd);
console.log('Aligned residues:', result.alignedLength);
// result.bTransform is a Mat4 to transform structure2 onto structure1
```
### TM-align Result
The `tmAlign` function returns a `TMAlignResult` object with the following properties:
| Property | Type | Description |
|----------|------|-------------|
| `bTransform` | `Mat4` | Transformation matrix to superpose structure B onto A |
| `tmScoreA` | `number` | TM-score normalized by length of structure A |
| `tmScoreB` | `number` | TM-score normalized by length of structure B |
| `rmsd` | `number` | RMSD of aligned residue pairs (in Angstroms) |
| `alignedLength` | `number` | Number of aligned residue pairs |
| `sequenceIdentity` | `number` | Sequence identity of aligned residues (0-1) |
| `alignmentA` | `number[]` | Indices of aligned residues in structure A |
| `alignmentB` | `number[]` | Indices of aligned residues in structure B |
### Understanding TM-score
The TM-score is calculated as:
$$\text{TM-score} = \frac{1}{L} \sum_{i=1}^{L_{ali}} \frac{1}{1 + (d_i/d_0)^2}$$
Where:
- $L$ is the length of the reference protein
- $L_{ali}$ is the number of aligned residues
- $d_i$ is the distance between the $i$-th pair of aligned residues after superposition
- $d_0 = 1.24 \sqrt[3]{L - 15} - 1.8$ is a length-dependent normalization factor
**TM-score interpretation:**
- TM-score > 0.5: Generally indicates proteins with the same fold
- TM-score > 0.17: Generally indicates proteins with random structural similarity
### Low-level API
For direct coordinate-based alignment without structures, use the `TMAlign` namespace:
```typescript
import { TMAlign } from 'molstar/lib/mol-math/linear-algebra/3d/tm-align';
// Create position arrays
const posA = TMAlign.Positions.empty(lengthA);
const posB = TMAlign.Positions.empty(lengthB);
// Fill in coordinates
for (let i = 0; i < lengthA; i++) {
posA.x[i] = /* x coordinate */;
posA.y[i] = /* y coordinate */;
posA.z[i] = /* z coordinate */;
}
// ... similarly for posB
// Compute alignment
const result = TMAlign.compute({ a: posA, b: posB });
```
### Complete Example: Aligning Two PDB Structures
```typescript
import { PluginContext } from 'molstar/lib/mol-plugin/context';
import { MolScriptBuilder as MS } from 'molstar/lib/mol-script/language/builder';
import { compile } from 'molstar/lib/mol-script/runtime/query/compiler';
import { StructureSelection, QueryContext, StructureElement } from 'molstar/lib/mol-model/structure';
import { tmAlign } from 'molstar/lib/mol-model/structure/structure/util/tm-align';
import { StateTransforms } from 'molstar/lib/mol-plugin-state/transforms';
import { Mat4 } from 'molstar/lib/mol-math/linear-algebra';
async function alignStructures(plugin: PluginContext, structure1: any, structure2: any) {
// Query for C-alpha atoms in chain A
const caQuery = compile<StructureSelection>(MS.struct.generator.atomGroups({
'chain-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.auth_asym_id(), 'A']),
'atom-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_atom_id(), 'CA'])
}));
// Get structure data
const data1 = structure1.cell?.obj?.data;
const data2 = structure2.cell?.obj?.data;
// Create selections
const sel1 = StructureSelection.toLociWithCurrentUnits(caQuery(new QueryContext(data1)));
const sel2 = StructureSelection.toLociWithCurrentUnits(caQuery(new QueryContext(data2)));
// Run TM-align
const result = tmAlign(sel1, sel2);
// Apply transformation to structure2
const b = plugin.state.data.build().to(structure2)
.insert(StateTransforms.Model.TransformStructureConformation, {
transform: { name: 'matrix', params: { data: result.bTransform, transpose: false } }
});
await plugin.runTask(plugin.state.data.updateTree(b));
return result;
}
```
## References
- Zhang Y, Skolnick J. "TM-align: a protein structure alignment algorithm based on the TM-score." *Nucleic Acids Research* 33, 2302-2309 (2005). DOI: [10.1093/nar/gki524](https://doi.org/10.1093/nar/gki524)
- Kabsch W. "A solution for the best rotation to relate two sets of vectors." *Acta Crystallographica* A32, 922-923 (1976).

View File

@@ -25,7 +25,6 @@ markdown_extensions:
generic: true
# Scripts for rendering Latex equations (in addition to pymdownx.arithmatex):
extra_javascript:
- https://polyfill.io/v3/polyfill.min.js?features=es6
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
nav:
- 'index.md'
@@ -34,10 +33,13 @@ nav:
- Examples: plugin/examples.md
- Custom Library: 'plugin/custom-library.md'
- Selections: 'plugin/selections.md'
- Superposition: 'plugin/superposition.md'
- Viewer State: 'plugin/viewer-state.md'
- Data State: 'plugin/data-state.md'
- File Formats: 'plugin/file-formats.md'
- CIF Schemas: 'plugin/cif-schemas.md'
- Managers:
- Markdown Extensions: 'plugin/managers/markdown-extensions.md'
- State Transforms:
- Custom Trajectory: 'plugin/transforms/custom-trajectory.md'
- Custom Conformation: 'plugin/transforms/custom-conformation.md'
@@ -56,7 +58,8 @@ nav:
- MolViewSpec: 'extensions/mvs/index.md'
- wwPDB StructConn: 'extensions/struct-conn.md'
- Tunnels: 'extensions/tunnels.md'
- Interactions: 'extensions/interactions.md'
- Misc:
- Interesting PDB entries: misc/interesting-pdb-entries.md
- Exporting component data: exporting-components.md
- Exporting component data: misc/exporting-components.md
repo_url: https://github.com/molstar/docs

111
eslint.config.mjs Normal file
View File

@@ -0,0 +1,111 @@
import { defineConfig } from "eslint/config";
import globals from "globals";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
export default defineConfig([{
ignores: [
"node_modules/*",
"build/*",
"deploy/*",
"docs/site/*",
"lib/*",
"eslint.config.mjs",
"build.mjs",
]
},{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
ecmaVersion: 2018,
sourceType: "module",
parserOptions: {
ecmaFeatures: {
impliedStrict: true,
},
},
},
rules: {
indent: "off",
"arrow-parens": ["off", "as-needed"],
"brace-style": ["error", "1tbs", {
allowSingleLine: true,
}],
"comma-spacing": "off",
"space-infix-ops": "off",
"comma-dangle": "off",
quotes: ["warn", "single", { "allowTemplateLiterals": true, "avoidEscape": true }],
eqeqeq: ["error", "smart"],
"import/order": "off",
"no-eval": "warn",
"no-extend-native": "warn",
"no-new-wrappers": "warn",
"no-trailing-spaces": "error",
"no-unsafe-finally": "warn",
"no-self-compare": "warn",
"no-var": "error",
"spaced-comment": "error",
semi: "warn",
"no-restricted-syntax": ["error", {
selector: "ExportDefaultDeclaration",
message: "Default exports are not allowed",
}],
"no-throw-literal": "error",
"key-spacing": "error",
"object-curly-spacing": ["error", "always"],
"array-bracket-spacing": "error",
"space-in-parens": "error",
"computed-property-spacing": "error",
"prefer-const": ["error", {
destructuring: "all",
ignoreReadBeforeAssign: false,
}],
"space-before-function-paren": "off",
"func-call-spacing": "off",
"no-multi-spaces": "error",
"block-spacing": "error",
"keyword-spacing": "warn",
"space-before-blocks": "error",
"semi-spacing": "error",
"no-constant-binary-expression": "error",
},
}, {
files: ["**/*.ts", "**/*.tsx"],
plugins: {
"@typescript-eslint": typescriptEslint,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 5,
sourceType: "module",
parserOptions: {
project: ["tsconfig.eslint.json"],
},
},
rules: {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/class-name-casing": "off",
"@typescript-eslint/member-delimiter-style": ["off", {
multiline: {
delimiter: "none",
requireLast: true,
},
singleline: {
delimiter: "semi",
requireLast: false,
},
}],
"@typescript-eslint/prefer-namespace-keyword": "warn",
"@typescript-eslint/semi": ["off", null],
},
}]);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,456 @@
forcefield_3904
RDKit 3D
49 52 0 0 0 0 0 0 0 0999 V2000
7.1950 23.7840 6.1780 C 0 0 0 0 0 0 0 0 0 0 0 0
5.7810 23.6440 6.1320 O 0 0 0 0 0 0 0 0 0 0 0 0
5.0380 24.7500 6.4550 C 0 0 0 0 0 0 0 0 0 0 0 0
4.8270 25.8570 5.6380 C 0 0 0 0 0 0 0 0 0 0 0 0
4.0460 26.9150 6.0970 C 0 0 0 0 0 0 0 0 0 0 0 0
3.4760 26.8670 7.3710 C 0 0 0 0 0 0 0 0 0 0 0 0
3.6720 25.7630 8.2160 C 0 0 0 0 0 0 0 0 0 0 0 0
3.0720 25.7780 9.4800 N 0 0 0 0 0 0 0 0 0 0 0 0
1.8090 25.4470 9.9650 C 0 0 0 0 0 0 0 0 0 0 0 0
0.8080 26.1730 9.4160 N 0 0 0 0 0 0 0 0 0 0 0 0
-0.4770 25.9480 9.8040 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.5110 26.6810 9.2540 O 0 0 0 0 0 0 0 0 0 0 0 0
-1.0950 27.9270 8.6960 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.1890 28.9860 8.9110 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.6300 30.4110 8.7600 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.7130 31.4650 8.9780 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.4040 31.2910 10.3270 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.9520 29.8780 10.4990 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.8690 28.8240 10.2810 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.7400 24.9710 10.7610 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.8850 24.4940 11.3660 N 0 0 0 0 0 0 0 0 0 0 0 0
-1.4690 23.5570 12.1930 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.1090 23.4080 12.1480 N 0 0 0 0 0 0 0 0 0 0 0 0
0.3700 24.3040 11.2380 C 0 0 0 0 0 0 0 0 0 0 0 0
1.6480 24.4860 10.8910 N 0 0 0 0 0 0 0 0 0 0 0 0
4.4600 24.7130 7.7330 C 0 0 0 0 0 0 0 0 0 0 0 0
7.5263 23.8168 7.2264 H 0 0 0 0 0 0 0 0 0 0 0 0
7.6649 22.9280 5.6716 H 0 0 0 0 0 0 0 0 0 0 0 0
7.4879 24.7155 5.6716 H 0 0 0 0 0 0 0 0 0 0 0 0
5.2751 25.8961 4.6342 H 0 0 0 0 0 0 0 0 0 0 0 0
3.8776 27.7913 5.4538 H 0 0 0 0 0 0 0 0 0 0 0 0
2.8616 27.7104 7.7192 H 0 0 0 0 0 0 0 0 0 0 0 0
3.6420 26.0930 10.2520 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.1673 28.2555 9.1874 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.9189 27.8009 7.6175 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.9466 28.8274 8.1294 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.8310 30.5615 9.5009 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.2424 30.5222 7.7366 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.2524 32.4632 8.9392 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.4689 31.3496 8.1873 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.6781 31.4924 11.1285 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.2475 31.9954 10.3749 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.3529 29.7723 11.5179 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.7404 29.7213 9.7481 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.1096 28.9239 11.0705 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.3427 27.8318 10.3148 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.1334 22.9663 12.8408 H 0 0 0 0 0 0 0 0 0 0 0 0
0.4510 22.7600 12.6820 H 0 0 0 0 0 0 0 0 0 0 0 0
4.6312 23.8345 8.3724 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
2 3 1 0
3 4 2 0
4 5 1 0
5 6 2 0
6 7 1 0
7 8 1 0
8 9 1 0
9 10 2 0
10 11 1 0
11 12 1 0
12 13 1 0
13 14 1 0
14 15 1 0
15 16 1 0
16 17 1 0
17 18 1 0
18 19 1 0
11 20 2 0
20 21 1 0
21 22 2 0
22 23 1 0
23 24 1 0
24 25 2 0
7 26 2 0
26 3 1 0
25 9 1 0
19 14 1 0
24 20 1 0
1 27 1 0
1 28 1 0
1 29 1 0
4 30 1 0
5 31 1 0
6 32 1 0
8 33 1 0
13 34 1 0
13 35 1 0
14 36 1 0
15 37 1 0
15 38 1 0
16 39 1 0
16 40 1 0
17 41 1 0
17 42 1 0
18 43 1 0
18 44 1 0
19 45 1 0
19 46 1 0
22 47 1 0
23 48 1 0
26 49 1 0
M END
> <ligandCode> (1)
forcefield_3904
> <ligandName> (1)
klr_22
$$$$
forcefield_3905
RDKit 3D
49 52 0 0 0 0 0 0 0 0999 V2000
6.5460 25.1350 3.8360 N 0 0 0 0 0 0 0 0 0 0 0 0
5.2550 25.5560 3.9960 C 0 0 0 0 0 0 0 0 0 0 0 0
4.5630 25.8360 3.0240 O 0 0 0 0 0 0 0 0 0 0 0 0
4.7190 25.6170 5.3820 C 0 0 0 0 0 0 0 0 0 0 0 0
4.0120 26.7570 5.7730 C 0 0 0 0 0 0 0 0 0 0 0 0
3.4880 26.8570 7.0690 C 0 0 0 0 0 0 0 0 0 0 0 0
3.6630 25.8340 8.0050 C 0 0 0 0 0 0 0 0 0 0 0 0
3.1640 25.8720 9.3110 N 0 0 0 0 0 0 0 0 0 0 0 0
1.9510 25.5250 9.9030 C 0 0 0 0 0 0 0 0 0 0 0 0
0.8900 26.1930 9.3960 N 0 0 0 0 0 0 0 0 0 0 0 0
-0.3560 25.9480 9.8850 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.4490 26.6220 9.3800 O 0 0 0 0 0 0 0 0 0 0 0 0
-1.1050 27.7730 8.6070 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.7010 29.0180 9.2810 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.5340 30.2520 8.3770 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.5490 31.3650 8.6570 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.0430 31.3400 10.0950 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.7320 30.0170 10.4330 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.1730 28.8170 9.6630 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.5160 25.0110 10.9050 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.5980 24.5310 11.6140 N 0 0 0 0 0 0 0 0 0 0 0 0
-1.0930 23.6490 12.4490 C 0 0 0 0 0 0 0 0 0 0 0 0
0.2630 23.5390 12.3140 N 0 0 0 0 0 0 0 0 0 0 0 0
0.6490 24.4020 11.3310 C 0 0 0 0 0 0 0 0 0 0 0 0
1.8910 24.6070 10.8850 N 0 0 0 0 0 0 0 0 0 0 0 0
4.3890 24.7010 7.5990 C 0 0 0 0 0 0 0 0 0 0 0 0
4.9170 24.5890 6.3060 C 0 0 0 0 0 0 0 0 0 0 0 0
7.0340 24.6220 4.5560 H 0 0 0 0 0 0 0 0 0 0 0 0
6.8360 24.9760 2.8790 H 0 0 0 0 0 0 0 0 0 0 0 0
3.8658 27.5811 5.0592 H 0 0 0 0 0 0 0 0 0 0 0 0
2.9275 27.7591 7.3554 H 0 0 0 0 0 0 0 0 0 0 0 0
3.7800 26.2290 10.0270 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.0105 27.8693 8.5543 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.5056 27.6720 7.5875 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.1446 29.1858 10.2149 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.5231 30.6584 8.5280 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.7027 29.9170 7.3429 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.0722 32.3370 8.4626 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.4156 31.2068 7.9983 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.1848 31.4776 10.7693 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.7762 32.1504 10.2201 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.6091 29.8266 11.5094 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.7879 30.1213 10.1428 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.2575 27.9194 10.2932 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.7539 28.7064 8.7355 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.6897 23.0698 13.1690 H 0 0 0 0 0 0 0 0 0 0 0 0
0.8800 22.9330 12.8360 H 0 0 0 0 0 0 0 0 0 0 0 0
4.5467 23.8809 8.3150 H 0 0 0 0 0 0 0 0 0 0 0 0
5.4866 23.6927 6.0193 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
2 3 2 0
2 4 1 0
4 5 2 0
5 6 1 0
6 7 2 0
7 8 1 0
8 9 1 0
9 10 2 0
10 11 1 0
11 12 1 0
12 13 1 0
13 14 1 0
14 15 1 0
15 16 1 0
16 17 1 0
17 18 1 0
18 19 1 0
11 20 2 0
20 21 1 0
21 22 2 0
22 23 1 0
23 24 1 0
24 25 2 0
7 26 1 0
26 27 2 0
27 4 1 0
25 9 1 0
19 14 1 0
24 20 1 0
1 28 1 0
1 29 1 0
5 30 1 0
6 31 1 0
8 32 1 0
13 33 1 0
13 34 1 0
14 35 1 0
15 36 1 0
15 37 1 0
16 38 1 0
16 39 1 0
17 40 1 0
17 41 1 0
18 42 1 0
18 43 1 0
19 44 1 0
19 45 1 0
22 46 1 0
23 47 1 0
26 48 1 0
27 49 1 0
M END
> <ligandCode> (2)
forcefield_3905
> <ligandName> (2)
1oiy-1
$$$$
forcefield_14264
RDKit 3D
50 53 0 0 0 0 0 0 0 0999 V2000
4.9220 23.4040 3.0090 N 0 0 0 0 0 0 0 0 0 0 0 0
5.8970 24.7200 3.4040 S 0 0 0 0 0 6 0 0 0 0 0 0
7.2120 24.2200 3.7260 O 0 0 0 0 0 0 0 0 0 0 0 0
5.6670 25.6980 2.3670 O 0 0 0 0 0 0 0 0 0 0 0 0
5.1310 25.2890 4.8970 C 0 0 0 0 0 0 0 0 0 0 0 0
4.3720 26.4580 4.8910 C 0 0 0 0 0 0 0 0 0 0 0 0
3.7730 26.8990 6.0760 C 0 0 0 0 0 0 0 0 0 0 0 0
3.9290 26.1970 7.2780 C 0 0 0 0 0 0 0 0 0 0 0 0
3.3430 26.5790 8.4890 N 0 0 0 0 0 0 0 0 0 0 0 0
2.1400 26.2820 9.1290 C 0 0 0 0 0 0 0 0 0 0 0 0
1.0830 26.9670 8.6370 N 0 0 0 0 0 0 0 0 0 0 0 0
-0.1520 26.7740 9.1730 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.2430 27.4630 8.6800 O 0 0 0 0 0 0 0 0 0 0 0 0
-0.9280 28.7750 8.2140 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.2060 29.6320 8.2420 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.2120 29.0810 9.2730 C 0 0 0 0 0 0 0 0 0 0 0 0
-4.1810 30.1570 9.7450 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.4520 31.3060 10.4440 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.0250 31.5210 9.9360 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.8770 31.1190 8.4740 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.3060 25.8730 10.2240 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.3770 25.4460 10.9810 N 0 0 0 0 0 0 0 0 0 0 0 0
-0.8720 24.5730 11.8270 C 0 0 0 0 0 0 0 0 0 0 0 0
0.4750 24.4190 11.6520 N 0 0 0 0 0 0 0 0 0 0 0 0
0.8530 25.2430 10.6320 C 0 0 0 0 0 0 0 0 0 0 0 0
2.0880 25.3990 10.1410 N 0 0 0 0 0 0 0 0 0 0 0 0
4.7090 25.0260 7.2550 C 0 0 0 0 0 0 0 0 0 0 0 0
5.3130 24.5730 6.0780 C 0 0 0 0 0 0 0 0 0 0 0 0
4.1960 23.3080 3.7210 H 0 0 0 0 0 0 0 0 0 0 0 0
5.4460 22.5390 2.8810 H 0 0 0 0 0 0 0 0 0 0 0 0
4.2447 27.0304 3.9603 H 0 0 0 0 0 0 0 0 0 0 0 0
3.1666 27.8167 6.0634 H 0 0 0 0 0 0 0 0 0 0 0 0
3.8380 27.2640 9.0420 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.1661 29.2261 8.8668 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.5358 28.7227 7.1876 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.6885 29.5690 7.2555 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.7847 28.2635 8.8106 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.6467 28.7218 10.1456 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.7231 30.5555 8.8747 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.8753 29.7014 10.4664 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.0232 32.2317 10.2804 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.3803 31.0434 11.5098 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.7667 32.5851 10.0403 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.3511 30.8895 10.5336 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.5603 31.7316 7.8675 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.8284 31.2816 8.1841 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.4619 24.0333 12.5825 H 0 0 0 0 0 0 0 0 0 0 0 0
1.0910 23.8110 12.1720 H 0 0 0 0 0 0 0 0 0 0 0 0
4.8468 24.4538 8.1843 H 0 0 0 0 0 0 0 0 0 0 0 0
5.9261 23.6598 6.0846 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
2 3 2 0
2 4 2 0
2 5 1 0
5 6 2 0
6 7 1 0
7 8 2 0
8 9 1 0
9 10 1 0
10 11 2 0
11 12 1 0
12 13 1 0
13 14 1 0
14 15 1 0
15 16 1 0
16 17 1 0
17 18 1 0
18 19 1 0
19 20 1 0
12 21 2 0
21 22 1 0
22 23 2 0
23 24 1 0
24 25 1 0
25 26 2 0
8 27 1 0
27 28 2 0
28 5 1 0
26 10 1 0
20 15 1 0
25 21 1 0
1 29 1 0
1 30 1 0
6 31 1 0
7 32 1 0
9 33 1 0
14 34 1 0
14 35 1 0
15 36 1 0
16 37 1 0
16 38 1 0
17 39 1 0
17 40 1 0
18 41 1 0
18 42 1 0
19 43 1 0
19 44 1 0
20 45 1 0
20 46 1 0
23 47 1 0
24 48 1 0
27 49 1 0
28 50 1 0
M END
> <ligandCode> (3)
forcefield_14264
> <ligandName> (3)
1h1s
$$$$
forcefield_14265
RDKit 3D
50 53 0 0 0 0 0 0 0 0999 V2000
5.9560 25.0880 4.1850 N 0 0 0 0 0 0 0 0 0 0 0 0
5.6880 24.2300 5.6100 S 0 0 0 0 0 6 0 0 0 0 0 0
4.9010 23.0800 5.2270 O 0 0 0 0 0 0 0 0 0 0 0 0
6.9470 24.1160 6.3060 O 0 0 0 0 0 0 0 0 0 0 0 0
4.6500 25.3510 6.5050 C 0 0 0 0 0 0 0 0 0 0 0 0
4.3190 26.5790 5.9340 C 0 0 0 0 0 0 0 0 0 0 0 0
3.4970 27.4490 6.6410 C 0 0 0 0 0 0 0 0 0 0 0 0
3.0220 27.0950 7.9100 C 0 0 0 0 0 0 0 0 0 0 0 0
3.3680 25.8770 8.5100 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9060 25.4620 9.7630 N 0 0 0 0 0 0 0 0 0 0 0 0
1.6520 25.1280 10.2760 C 0 0 0 0 0 0 0 0 0 0 0 0
0.6590 25.9320 9.8350 N 0 0 0 0 0 0 0 0 0 0 0 0
-0.6150 25.7270 10.2650 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.6410 26.5420 9.8330 O 0 0 0 0 0 0 0 0 0 0 0 0
-1.2650 27.5510 8.8940 C 0 0 0 0 0 0 0 0 0 0 0 0
-1.4150 28.9670 9.4830 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.0650 29.8960 8.4420 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.7130 31.1080 9.0990 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.8410 30.6980 10.0490 C 0 0 0 0 0 0 0 0 0 0 0 0
-3.6490 29.3080 10.6570 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.1750 28.9600 10.8270 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.8720 24.6910 11.1610 C 0 0 0 0 0 0 0 0 0 0 0 0
-2.0060 24.2140 11.7870 N 0 0 0 0 0 0 0 0 0 0 0 0
-1.5910 23.2030 12.5210 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.2430 23.0050 12.3980 N 0 0 0 0 0 0 0 0 0 0 0 0
0.2320 23.9470 11.5330 C 0 0 0 0 0 0 0 0 0 0 0 0
1.5000 24.1080 11.1380 N 0 0 0 0 0 0 0 0 0 0 0 0
4.1890 25.0030 7.7800 C 0 0 0 0 0 0 0 0 0 0 0 0
6.4350 24.4790 3.5180 H 0 0 0 0 0 0 0 0 0 0 0 0
5.1080 25.4920 3.7910 H 0 0 0 0 0 0 0 0 0 0 0 0
4.7020 26.8549 4.9404 H 0 0 0 0 0 0 0 0 0 0 0 0
3.2187 28.4186 6.2023 H 0 0 0 0 0 0 0 0 0 0 0 0
2.3612 27.7900 8.4488 H 0 0 0 0 0 0 0 0 0 0 0 0
3.5640 25.4960 10.5280 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.2150 27.3950 8.6054 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.9312 27.4715 8.0223 H 0 0 0 0 0 0 0 0 0 0 0 0
-0.4134 29.3591 9.7135 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.2920 30.2413 7.7397 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.8482 29.3296 7.9168 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.9484 31.6568 9.6685 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.1423 31.7400 8.3076 H 0 0 0 0 0 0 0 0 0 0 0 0
-3.8921 31.4320 10.8667 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.7682 30.6682 9.4579 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.1367 29.2806 11.6426 H 0 0 0 0 0 0 0 0 0 0 0 0
-4.0960 28.5721 9.9724 H 0 0 0 0 0 0 0 0 0 0 0 0
-1.7122 29.6974 11.4994 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.1140 27.9439 11.2440 H 0 0 0 0 0 0 0 0 0 0 0 0
-2.2486 22.5915 13.1563 H 0 0 0 0 0 0 0 0 0 0 0 0
0.3120 22.2980 12.8550 H 0 0 0 0 0 0 0 0 0 0 0 0
4.4733 24.0335 8.2150 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0
2 3 2 0
2 4 2 0
2 5 1 0
5 6 2 0
6 7 1 0
7 8 2 0
8 9 1 0
9 10 1 0
10 11 1 0
11 12 2 0
12 13 1 0
13 14 1 0
14 15 1 0
15 16 1 0
16 17 1 0
17 18 1 0
18 19 1 0
19 20 1 0
20 21 1 0
13 22 2 0
22 23 1 0
23 24 2 0
24 25 1 0
25 26 1 0
26 27 2 0
9 28 2 0
28 5 1 0
27 11 1 0
21 16 1 0
26 22 1 0
1 29 1 0
1 30 1 0
6 31 1 0
7 32 1 0
8 33 1 0
10 34 1 0
15 35 1 0
15 36 1 0
16 37 1 0
17 38 1 0
17 39 1 0
18 40 1 0
18 41 1 0
19 42 1 0
19 43 1 0
20 44 1 0
20 45 1 0
21 46 1 0
21 47 1 0
24 48 1 0
25 49 1 0
28 50 1 0
M END
> <ligandCode> (4)
forcefield_14265
> <ligandName> (4)
1oiu
$$$$

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,264 @@
%VERSION VERSION_STAMP = V0001.000 DATE = 11/04/25 11:55:47
%FLAG TITLE
%FORMAT(20a4)
alanine-dipeptide.solvated.pdb
%FLAG POINTERS
%FORMAT(10I8)
22 7 12 9 25 11 39 19 0 0
99 3 9 11 19 7 11 20 0 0
0 0 0 0 0 0 0 1 10 0
0 1
%FLAG ATOM_NAME
%FORMAT(20a4)
H1 CH3 H2 H3 C O N H CA HA CB HB1 HB2 HB3 C O N H C H1
H2 H3
%FLAG ATOMIC_NUMBER
%FORMAT(10I8)
1 6 1 1 6 8 7 1 6 1
6 1 1 1 6 8 7 1 6 1
1 1
%FLAG RESIDUE_LABEL
%FORMAT(20a4)
ACE ALA NME
%FLAG RESIDUE_POINTER
%FORMAT(10I8)
1 7 17
%FLAG RESIDUE_NUMBER
%FORMAT(20I4)
1 2 3
%FLAG RESIDUE_ICODE
%FORMAT(20a4)
%FLAG RESIDUE_CHAINID
%FORMAT(20a4)
B B B
%FLAG SOLVENT_POINTERS
%FORMAT(3I8)
0 1 0
%FLAG ATOMS_PER_MOLECULE
%FORMAT(10I8)
22
%FLAG MASS
%FORMAT(5E16.8)
3.02400000E+00 5.96200000E+00 3.02400000E+00 3.02400000E+00 1.20100000E+01
1.60000000E+01 1.19940000E+01 3.02400000E+00 9.99400000E+00 3.02400000E+00
5.96200000E+00 3.02400000E+00 3.02400000E+00 3.02400000E+00 1.20100000E+01
1.60000000E+01 1.19940000E+01 3.02400000E+00 5.96200000E+00 3.02400000E+00
3.02400000E+00 3.02400000E+00
%FLAG CHARGE
%FORMAT(5E16.8)
2.04636429E+00 -6.67300626E+00 2.04636429E+00 2.04636429E+00 1.08823576E+01
-1.03484442E+01 -7.57501011E+00 4.95464337E+00 6.14091510E-01 1.49969529E+00
-3.32556975E+00 1.09880469E+00 1.09880469E+00 1.09880469E+00 1.08841798E+01
-1.03484442E+01 -7.57501011E+00 4.95464337E+00 -2.71512270E+00 1.77849648E+00
1.77849648E+00 1.77849648E+00
%FLAG AMBER_ATOM_TYPE
%FORMAT(20a4)
a0 a1 a0 a0 a2 a3 a4 a5 a1 a6 a1 a0 a0 a0 a2 a3 a4 a5 a1 a6
a6 a6
%FLAG ATOM_TYPE_INDEX
%FORMAT(10I8)
1 2 1 1 3 4 5 6 2 7
2 1 1 1 3 4 5 6 2 7
7 7
%FLAG NONBONDED_PARM_INDEX
%FORMAT(10I8)
1 2 4 7 11 16 22 2 3 5
8 12 17 23 4 5 6 9 13 18
24 7 8 9 10 14 19 25 11 12
13 14 15 20 26 16 17 18 19 20
21 27 22 23 24 25 26 27 28
%FLAG LENNARD_JONES_ACOEF
%FORMAT(5E16.8)
7.51607703E+03 9.71708117E+04 1.04308023E+06 8.61541883E+04 9.24822269E+05
8.19971662E+05 5.44261042E+04 6.47841732E+05 5.74393458E+05 3.79876399E+05
8.96776989E+04 9.95480466E+05 8.82619071E+05 6.06829343E+05 9.44293233E+05
1.07193645E+02 2.56678134E+03 2.27577560E+03 1.02595236E+03 2.12601181E+03
1.39982777E-01 4.98586847E+03 6.78771368E+04 6.01816484E+04 3.69471530E+04
6.20665998E+04 5.94667299E+01 3.25969625E+03
%FLAG LENNARD_JONES_BCOEF
%FORMAT(5E16.8)
2.17257828E+01 1.26919150E+02 6.75612247E+02 1.12529845E+02 5.99015525E+02
5.31102864E+02 1.11805549E+02 6.26720080E+02 5.55666449E+02 5.64885984E+02
1.36131731E+02 7.36907417E+02 6.53361429E+02 6.77220874E+02 8.01323529E+02
2.59456373E+00 2.06278363E+01 1.82891803E+01 1.53505284E+01 2.09604198E+01
9.37598976E-02 1.76949863E+01 1.06076943E+02 9.40505981E+01 9.21192137E+01
1.13252062E+02 1.93248820E+00 1.43076527E+01
%FLAG NUMBER_EXCLUDED_ATOMS
%FORMAT(10I8)
6 7 4 3 7 3 10 4 10 7
6 3 2 1 7 3 5 4 3 2
1 1
%FLAG EXCLUDED_ATOMS_LIST
%FORMAT(10I8)
2 3 4 5 6 7 3 4 5 6
7 8 9 4 5 6 7 5 6 7
6 7 8 9 10 11 15 7 8 9
8 9 10 11 12 13 14 15 16 17
9 10 11 15 10 11 12 13 14 15
16 17 18 19 11 12 13 14 15 16
17 12 13 14 15 16 17 13 14 15
14 15 15 16 17 18 19 20 21 22
17 18 19 18 19 20 21 22 19 20
21 22 20 21 22 21 22 22 0
%FLAG BOND_FORCE_CONSTANT
%FORMAT(5E16.8)
3.40000000E+02 4.34000000E+02 3.17000000E+02 5.70000000E+02 4.90000000E+02
3.37000000E+02 3.10000000E+02
%FLAG BOND_EQUIL_VALUE
%FORMAT(5E16.8)
1.09000000E+00 1.01000000E+00 1.52200000E+00 1.22900000E+00 1.33500000E+00
1.44900000E+00 1.52600000E+00
%FLAG BONDS_INC_HYDROGEN
%FORMAT(10I8)
0 3 1 3 6 1 3 9 1 18
21 2 24 27 1 30 33 1 30 36
1 30 39 1 48 51 2 54 57 1
54 60 1 54 63 1
%FLAG BONDS_WITHOUT_HYDROGEN
%FORMAT(10I8)
3 12 3 12 15 4 12 18 5 18
24 6 24 42 3 24 30 7 42 48
5 42 45 4 48 54 6
%FLAG ANGLE_FORCE_CONSTANT
%FORMAT(5E16.8)
3.50000000E+01 5.00000000E+01 5.00000000E+01 5.00000000E+01 8.00000000E+01
7.00000000E+01 5.00000000E+01 8.00000000E+01 8.00000000E+01 6.30000000E+01
6.30000000E+01
%FLAG ANGLE_EQUIL_VALUE
%FORMAT(5E16.8)
1.91113553E+00 1.91113553E+00 2.09439510E+00 2.06018665E+00 2.10137642E+00
2.03505391E+00 2.12755636E+00 2.14500965E+00 1.91462619E+00 1.92160751E+00
1.93906080E+00
%FLAG ANGLES_INC_HYDROGEN
%FORMAT(10I8)
0 3 6 1 0 3 9 1 0 3
12 2 6 3 9 1 6 3 12 2
9 3 12 2 12 18 21 3 18 24
27 2 21 18 24 4 24 30 33 2
24 30 36 2 24 30 39 2 27 24
30 2 27 24 42 2 33 30 36 1
33 30 39 1 36 30 39 1 42 48
51 3 48 54 57 2 48 54 60 2
48 54 63 2 51 48 54 4 57 54
60 1 57 54 63 1 60 54 63 1
%FLAG ANGLES_WITHOUT_HYDROGEN
%FORMAT(10I8)
3 12 15 5 3 12 18 6 12 18
24 7 15 12 18 8 18 24 30 9
18 24 42 10 24 42 45 5 24 42
48 6 30 24 42 11 42 48 54 7
45 42 48 8
%FLAG DIHEDRAL_FORCE_CONSTANT
%FORMAT(5E16.8)
8.00000000E-01 8.00000000E-02 2.50000000E+00 2.50000000E+00 2.00000000E+00
1.55555556E-01 1.10000000E+00 0.00000000E+00 0.00000000E+00 8.00000000E-01
1.80000000E+00 4.20000000E-01 2.70000000E-01 5.50000000E-01 1.58000000E+00
4.50000000E-01 4.00000000E-01 2.00000000E-01 2.00000000E-01 1.05000000E+01
%FLAG DIHEDRAL_PERIODICITY
%FORMAT(5E16.8)
1.00000000E+00 3.00000000E+00 2.00000000E+00 2.00000000E+00 1.00000000E+00
3.00000000E+00 2.00000000E+00 1.00000000E+00 1.00000000E+00 3.00000000E+00
2.00000000E+00 3.00000000E+00 2.00000000E+00 3.00000000E+00 2.00000000E+00
1.00000000E+00 3.00000000E+00 2.00000000E+00 1.00000000E+00 2.00000000E+00
%FLAG DIHEDRAL_PHASE
%FORMAT(5E16.8)
0.00000000E+00 3.14159265E+00 3.14159265E+00 3.14159265E+00 0.00000000E+00
0.00000000E+00 3.14159265E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 3.14159265E+00 3.14159265E+00
3.14159265E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 3.14159265E+00
%FLAG SCEE_SCALE_FACTOR
%FORMAT(5E16.8)
1.20000000E+00 0.00000000E+00 1.20000000E+00 1.20000000E+00 0.00000000E+00
1.20000000E+00 0.00000000E+00 1.20000000E+00 1.20000000E+00 1.20000000E+00
0.00000000E+00 1.20000000E+00 0.00000000E+00 1.20000000E+00 0.00000000E+00
0.00000000E+00 1.20000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
%FLAG SCNB_SCALE_FACTOR
%FORMAT(5E16.8)
2.00000000E+00 0.00000000E+00 2.00000000E+00 2.00000000E+00 0.00000000E+00
2.00000000E+00 0.00000000E+00 2.00000000E+00 2.00000000E+00 2.00000000E+00
0.00000000E+00 2.00000000E+00 0.00000000E+00 2.00000000E+00 0.00000000E+00
0.00000000E+00 2.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
%FLAG DIHEDRALS_INC_HYDROGEN
%FORMAT(10I8)
0 3 12 15 1 0 3 -12 15 2
3 12 18 21 3 6 3 12 15 1
6 3 -12 15 2 9 3 12 15 1
9 3 -12 15 2 15 12 18 21 4
15 12 -18 21 5 18 24 30 33 6
18 24 30 36 6 18 24 30 39 6
24 42 48 51 3 27 24 30 33 6
27 24 30 36 6 27 24 30 39 6
27 24 42 45 1 27 24 -42 45 2
42 24 30 33 6 42 24 30 36 6
42 24 30 39 6 45 42 48 51 4
45 42 -48 51 5 21 18 -24 -12 7
51 48 -54 -42 7 51 48 54 60 8
21 18 24 30 8 42 48 54 57 8
6 3 12 18 9 42 48 54 63 8
51 48 54 57 8 21 18 24 42 8
0 3 12 18 9 42 48 54 60 8
27 24 42 48 8 21 18 24 27 8
51 48 54 63 8 9 3 12 18 9
12 18 24 27 8
%FLAG DIHEDRALS_WITHOUT_HYDROGEN
%FORMAT(10I8)
3 12 18 24 3 12 18 24 30 10
12 18 -24 30 11 12 18 -24 30 5
12 18 24 42 12 12 18 -24 42 13
15 12 18 24 3 18 24 42 48 14
18 24 -42 48 15 18 24 -42 48 16
24 42 48 54 3 30 24 42 48 17
30 24 -42 48 18 30 24 -42 48 19
45 42 48 54 3 15 12 -18 -3 20
45 42 -48 -24 20 18 24 42 45 8
30 24 42 45 8
%FLAG SOLTY
%FORMAT(5E16.8)
%FLAG HBOND_ACOEF
%FORMAT(5E16.8)
%FLAG HBOND_BCOEF
%FORMAT(5E16.8)
%FLAG HBCUT
%FORMAT(5E16.8)
%FLAG TREE_CHAIN_CLASSIFICATION
%FORMAT(20a4)
BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA
BLA BLA
%FLAG JOIN_ARRAY
%FORMAT(10I8)
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0
%FLAG IROTAT
%FORMAT(10I8)
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0
%FLAG BOX_DIMENSIONS
%FORMAT(5E16.8)
9.00000000E+01 3.00000000E+01 3.00000000E+01 3.00000000E+01
%FLAG RADIUS_SET
%FORMAT(1a80)
0
%FLAG RADII
%FORMAT(5E16.8)
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00
%FLAG SCREEN
%FORMAT(5E16.8)
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00 0.00000000E+00
0.00000000E+00 0.00000000E+00
%FLAG IPOL
%FORMAT(1I8)
0

View File

@@ -0,0 +1,26 @@
CRYST1 30.000 30.000 30.000 90.00 90.00 90.00 P 1 1
ATOM 1 H1 ACE A 1 2.000 1.000 -0.000 0.00 0.00 H
ATOM 2 CH3 ACE A 1 2.000 2.090 0.000 0.00 0.00 C
ATOM 3 H2 ACE A 1 1.486 2.454 0.890 0.00 0.00 H
ATOM 4 H3 ACE A 1 1.486 2.454 -0.890 0.00 0.00 H
ATOM 5 C ACE A 1 3.427 2.641 -0.000 0.00 0.00 C
ATOM 6 O ACE A 1 4.391 1.877 -0.000 0.00 0.00 O
ATOM 7 N ALA A 2 3.555 3.970 -0.000 0.00 0.00 N
ATOM 8 H ALA A 2 2.733 4.556 -0.000 0.00 0.00 H
ATOM 9 CA ALA A 2 4.853 4.614 -0.000 0.00 0.00 C
ATOM 10 HA ALA A 2 5.408 4.316 0.890 0.00 0.00 H
ATOM 11 CB ALA A 2 5.661 4.221 -1.232 0.00 0.00 C
ATOM 12 HB1 ALA A 2 5.123 4.521 -2.131 0.00 0.00 H
ATOM 13 HB2 ALA A 2 6.630 4.719 -1.206 0.00 0.00 H
ATOM 14 HB3 ALA A 2 5.809 3.141 -1.241 0.00 0.00 H
ATOM 15 C ALA A 2 4.713 6.129 0.000 0.00 0.00 C
ATOM 16 O ALA A 2 3.601 6.653 0.000 0.00 0.00 O
ATOM 17 N NME A 3 5.846 6.835 0.000 0.00 0.00 N
ATOM 18 H NME A 3 6.737 6.359 -0.000 0.00 0.00 H
ATOM 19 C NME A 3 5.846 8.284 0.000 0.00 0.00 C
ATOM 20 H1 NME A 3 4.819 8.648 0.000 0.00 0.00 H
ATOM 21 H2 NME A 3 6.360 8.648 0.890 0.00 0.00 H
ATOM 22 H3 NME A 3 6.360 8.648 -0.890 0.00 0.00 H
TER 23 NME A 3
CONECT 5 7
CONECT 15 17

View File

@@ -0,0 +1,14 @@
alanine-dipeptide.solvated.pdb
22
0.7494821 1.2436848 0.8743532 1.0856344 2.2423820 0.5955986
0.4304414 2.9747953 1.0671825 1.0497815 2.3544810 -0.4880289
2.5015950 2.4471725 1.0820421 3.1003812 1.5343071 1.6479120
3.0220696 3.6519467 0.8741013 2.4411554 4.3533213 0.4373955
4.3920715 4.0500473 1.2160543 4.7674596 3.4172266 2.0202454
5.2805058 3.8202998 -0.0180103 4.9565949 4.4537317 -0.8438106
6.3180425 4.0583459 0.2164072 5.2327259 2.7740601 -0.3200050
4.4431625 5.5106563 1.7135265 3.4307644 6.2198007 1.6891606
5.6170320 5.9613562 2.1744082 6.3997462 5.3231585 2.1616313
5.8784762 7.3296314 2.6320299 5.1056278 8.0184146 2.2908769
5.9253575 7.3544224 3.7207393 6.8360338 7.6745804 2.2419090
30.0000000 30.0000000 30.0000000 90.0000000 90.0000000 90.0000000

21683
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "4.10.0",
"version": "5.9.0",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {
@@ -10,29 +10,30 @@
"bugs": {
"url": "https://github.com/molstar/molstar/issues"
},
"engines": {
"node": ">=22.0.0"
},
"scripts": {
"lint": "eslint .",
"lint-fix": "eslint . --fix",
"test": "npm install --no-save \"gl@^6.0.2\" && npm run lint && jest",
"jest": "jest",
"build": "npm run build-tsc && npm run build-extra && npm run build-webpack",
"clean": "node ./scripts/clean.js",
"clean": "node ./scripts/clean.js --all",
"clean:build": "node ./scripts/clean.js --build",
"build": "npm run build:apps && npm run build:lib",
"build:apps": "node ./scripts/build.mjs -a -e --prd",
"build:lib": "concurrently \"tsc --incremental\" \"tsc --build tsconfig.commonjs.json --incremental\" && npm run build:lib-extra",
"build:lib-extra": "node scripts/write-version.mjs && cpx \"src/**/*.{scss,html,ico,jpg}\" lib/ && cpx \"src/**/*.{scss,html,ico,jpg}\" lib/commonjs/ && tsc-alias -p tsconfig.json",
"rebuild": "npm run clean && npm run build",
"build-viewer": "npm run build-tsc && npm run build-extra && npm run build-webpack-viewer",
"build-tsc": "concurrently \"tsc --incremental\" \"tsc --build tsconfig.commonjs.json --incremental\"",
"build-extra": "cpx \"src/**/*.{scss,html,ico,jpg}\" lib/",
"build-webpack": "webpack --mode production --config ./webpack.config.production.js",
"build-webpack-viewer": "webpack --mode production --config ./webpack.config.viewer.js",
"watch": "concurrently -c \"green,green,gray,gray\" --names \"tsc,srv,ext,wpc\" --kill-others \"npm:watch-tsc\" \"npm:watch-servers\" \"npm:watch-extra\" \"npm:watch-webpack\"",
"watch-viewer": "concurrently -c \"green,gray,gray\" --names \"tsc,ext,wpc\" --kill-others \"npm:watch-tsc\" \"npm:watch-extra\" \"npm:watch-webpack-viewer\"",
"watch-viewer-debug": "concurrently -c \"green,gray,gray\" --names \"tsc,ext,wpc\" --kill-others \"npm:watch-tsc\" \"npm:watch-extra\" \"npm:watch-webpack-viewer-debug\"",
"watch-tsc": "tsc --watch --incremental",
"watch-servers": "tsc --build tsconfig.commonjs.json --watch --incremental",
"watch-extra": "cpx \"src/**/*.{scss,html,ico,jpg}\" lib/ --watch",
"watch-webpack": "webpack -w --mode development --stats minimal",
"watch-webpack-viewer": "webpack -w --mode development --stats minimal --config ./webpack.config.viewer.js",
"watch-webpack-viewer-debug": "webpack -w --mode development --stats minimal --config ./webpack.config.viewer.debug.js",
"dev": "node ./scripts/build.mjs",
"dev:all": "node ./scripts/build.mjs -a -e -bt",
"dev:viewer": "node ./scripts/build.mjs -a viewer",
"dev:apps": "node ./scripts/build.mjs -a",
"dev:examples": "node ./scripts/build.mjs -e",
"dev:browser-tests": "node ./scripts/build.mjs -bt",
"serve": "http-server -p 1338 -g",
"deploy:local": "npm run clean:build && npm run build:apps && node ./scripts/deploy.js --local",
"deploy:remote": "npm run clean:build && npm run build:apps && node ./scripts/deploy.js",
"model-server": "node lib/commonjs/servers/model/server.js",
"model-server-watch": "nodemon --watch lib lib/commonjs/servers/model/server.js",
"volume-server-test": "node lib/commonjs/servers/volume/server.js --idMap em 'test/${id}.mdb' --defaultPort 1336",
@@ -43,7 +44,8 @@
},
"files": [
"lib/",
"build/viewer/"
"build/viewer/",
"build/mvs-stories/"
],
"bin": {
"cif2bcif": "lib/commonjs/cli/cif2bcif/index.js",
@@ -72,7 +74,7 @@
"js"
],
"transform": {
"\\.ts$": "ts-jest"
"\\.ts$": ["esbuild-jest-transform", { "tsconfigRaw": "{\"compilerOptions\":{\"useDefineForClassFields\":false}}" }]
},
"moduleDirectories": [
"node_modules",
@@ -114,68 +116,68 @@
"Eric E <etongfu@outlook.com>",
"Xavier Martinez <xavier.martinez.xm@gmail.com>",
"Alex Chan <smalldirkalex@gmail.com>",
"Simeon Borko <simeon.borko@gmail.com>"
"Simeon Borko <simeon.borko@gmail.com>",
"Ventura Rivera <venturaxrivera@gmail.com>",
"Andy Turner <agdturner@gmail.com>",
"Lukáš Polák <admin@lukaspolak.cz>",
"Chetan Mishra <chetan.s115@gmail.com>",
"Zach Charlop-Powers <zach.charlop.powers@gmail.com>",
"Kim Juho <juho_kim@outlook.com>",
"Victoria Doshchenko <doshchenko.victoria@gmail.com>",
"Diego del Alamo <diego.delalamo@gmail.com>",
"Tianzhen Lin (Tangent) <tangent@usa.net>"
],
"license": "MIT",
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/cors": "^2.8.19",
"@types/gl": "^6.0.5",
"@types/jest": "^29.5.14",
"@types/jest": "^30.0.0",
"@types/pngjs": "^6.0.5",
"@types/react": "^18.3.16",
"@types/react-dom": "^18.3.5",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@types/react": "^18.3.28",
"@types/react-dom": "^18.3.7",
"@types/webxr": "^0.5.24",
"@typescript-eslint/eslint-plugin": "^8.59.1",
"@typescript-eslint/parser": "^8.59.1",
"benchmark": "^2.1.4",
"concurrently": "^9.1.0",
"cpx2": "^8.0.0",
"crypto-browserify": "^3.12.1",
"css-loader": "^7.1.2",
"eslint": "^8.57.1",
"extra-watch-webpack-plugin": "^1.0.3",
"file-loader": "^6.2.0",
"fs-extra": "^11.2.0",
"concurrently": "^9.2.1",
"cpx2": "^8.0.2",
"css-loader": "^7.1.4",
"esbuild": "^0.28.0",
"esbuild-jest-transform": "^2.0.1",
"esbuild-sass-plugin": "^3.7.0",
"eslint": "^10.3.0",
"fs-extra": "^11.3.4",
"globals": "^17.6.0",
"http-server": "^14.1.1",
"jest": "^29.7.0",
"jest": "^30.3.0",
"jpeg-js": "^0.4.4",
"mini-css-extract-plugin": "^2.9.2",
"path-browserify": "^1.0.1",
"raw-loader": "^4.0.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.83.0",
"sass-loader": "^16.0.4",
"simple-git": "^3.27.0",
"stream-browserify": "^3.0.0",
"style-loader": "^4.0.0",
"ts-jest": "^29.2.5",
"typescript": "^5.7.2",
"webpack": "^5.97.1",
"webpack-cli": "^5.1.4"
"sass": "^1.99.0",
"simple-git": "^3.36.0",
"tsc-alias": "^1.8.17",
"typescript": "^6.0.3"
},
"dependencies": {
"@types/argparse": "^2.0.17",
"@types/benchmark": "^2.1.5",
"@types/compression": "1.7.5",
"@types/express": "^5.0.0",
"@types/node": "^18.19.68",
"@types/node-fetch": "^2.6.12",
"@types/swagger-ui-dist": "3.30.5",
"@types/compression": "1.8.1",
"@types/express": "^5.0.6",
"@types/node": "^22.19.17",
"@types/swagger-ui-dist": "3.30.6",
"argparse": "^2.0.1",
"compression": "^1.7.5",
"cors": "^2.8.5",
"express": "^5.0.1",
"compression": "^1.8.1",
"cors": "^2.8.6",
"express": "^5.2.1",
"h264-mp4-encoder": "^1.0.12",
"immer": "^10.1.1",
"immutable": "^5.0.3",
"immutable": "^5.1.5",
"io-ts": "^2.2.22",
"node-fetch": "^2.7.0",
"react-markdown": "^9.0.1",
"rxjs": "^7.8.1",
"swagger-ui-dist": "^5.18.2",
"tslib": "^2.8.1",
"util.promisify": "^1.1.2",
"xhr2": "^0.2.1"
"mutative": "^1.3.0",
"react-markdown": "^10.1.0",
"remark-gfm": "^4.0.1",
"rxjs": "^7.8.2",
"swagger-ui-dist": "^5.32.5",
"tslib": "^2.8.1"
},
"peerDependencies": {
"@google-cloud/storage": "^7.14.0",

350
scripts/build.mjs Normal file
View File

@@ -0,0 +1,350 @@
/**
* Copyright (c) 2017-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Eric E <etongfu@@outlook.com>
*/
import * as esbuild from 'esbuild';
import * as fs from 'fs';
import * as path from 'path';
import * as argparse from 'argparse';
import { sassPlugin } from 'esbuild-sass-plugin';
import * as os from 'os';
const Apps = [
// Apps
{ kind: 'app', name: 'viewer', themes: ['light', 'dark', 'blue'] },
{ kind: 'app', name: 'docking-viewer' },
{ kind: 'app', name: 'mesoscale-explorer' },
{ kind: 'app', name: 'mvs-stories', globalName: 'mvsStories', filename: 'mvs-stories.js' },
// Examples
{ kind: 'example', name: 'proteopedia-wrapper' },
{ kind: 'example', name: 'basic-wrapper' },
{ kind: 'example', name: 'lighting' },
{ kind: 'example', name: 'alpha-orbitals' },
{ kind: 'example', name: 'alphafolddb-pae' },
{ kind: 'example', name: 'mvs-stories' },
{ kind: 'example', name: 'ihm-restraints' },
{ kind: 'example', name: 'interactions' },
{ kind: 'example', name: 'ligand-editor' },
];
function findApp(name, kind) {
return Apps.find(a => a.name === name && a.kind === kind);
}
function mkDir(dir) {
try {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
} catch (error) {
console.error(`Failed to create directory ${dir}:`, error);
process.exit(1);
}
}
function handleFileError(error, operation, path) {
console.error(`Failed to ${operation} ${path}:`, error);
process.exit(1);
}
function fileLoaderPlugin(options) {
mkDir(options.out);
return {
name: 'file-loader',
setup(build) {
build.onLoad({ filter: /\.jpg$/ }, async (args) => {
try {
const name = path.basename(args.path);
mkDir(path.resolve(options.out, 'images'));
await fs.promises.copyFile(args.path, path.resolve(options.out, 'images', name));
return {
contents: `images/${name}`,
loader: 'text',
};
} catch (error) {
handleFileError(error, 'copy', args.path);
}
});
build.onLoad({ filter: /\.(html|ico)$/ }, async (args) => {
const name = path.basename(args.path);
await fs.promises.copyFile(args.path, path.resolve(options.out, name));
return {
contents: '',
loader: 'empty',
};
});
},
};
}
function examplesCssRenamePlugin({ root }) {
return {
name: 'example-css-rename',
setup(build) {
build.onEnd(async () => {
if (fs.existsSync(path.resolve(root, 'index.css'))) {
await fs.promises.rename(
path.resolve(root, 'index.css'),
path.resolve(root, 'molstar.css')
);
}
});
}
};
}
function resolveEntryPath(path) {
if (!fs.existsSync(path)) {
return path + 'x'; // fallback to .tsx
}
return path;
}
function getPaths(app) {
if (app.kind === 'app') {
return {
prefix: `./build/${app.name}`,
entry: resolveEntryPath(`./src/apps/${app.name}/index.ts`),
outfile: `./build/${app.name}/${app.filename || 'molstar.js'}`,
};
}
if (app.kind === 'example') {
return {
prefix: `./build/examples/${app.name}`,
entry: resolveEntryPath(`./src/examples/${app.name}/index.ts`),
outfile: `./build/examples/${app.name}/${app.filename || 'index.js'}`,
};
}
if (app.kind === 'browser-test') {
return {
prefix: `./build/tests/browser`,
entry: resolveEntryPath(`./src/tests/browser/${app.name}.ts`),
outfile: `./build/tests/browser/${app.name}.js`,
};
}
throw new Error(`Unknown app kind: ${app.kind}`);
}
async function createBundle(app) {
const { name, kind } = app;
const { prefix, entry, outfile } = getPaths(app);
const ctx = await esbuild.context({
entryPoints: [entry],
tsconfig: './tsconfig.json',
bundle: true,
minify: isProduction,
minifyIdentifiers: false,
sourcemap: includeSourceMap,
globalName: app.globalName || 'molstar',
outfile,
plugins: [
fileLoaderPlugin({ out: prefix }),
sassPlugin({
type: 'css',
silenceDeprecations: ['import'],
logger: {
warn: (msg) => console.warn(msg),
debug: () => { },
}
}),
...(kind === 'example' ? [examplesCssRenamePlugin({ root: prefix })] : []),
],
external: ['crypto', 'fs', 'path', 'stream'],
loader: {
},
color: true,
logLevel: 'info',
define: {
'process.env.NODE_ENV': JSON.stringify(NODE_ENV_PRD ? 'production' : 'development'),
'process.env.DEBUG': JSON.stringify(process.env.DEBUG || false),
__MOLSTAR_PLUGIN_VERSION__: JSON.stringify(VERSION),
__MOLSTAR_BUILD_TIMESTAMP__: `${TIMESTAMP}`,
},
});
await ctx.rebuild();
if (!isProduction) await ctx.watch();
}
async function createTheme(appName, themeName) {
// const { prefix, entry, outfile } = getPaths(app);
const ctx = await esbuild.context({
entryPoints: [resolveEntryPath(`./src/apps/${appName}/theme/${themeName}.ts`)],
tsconfig: './tsconfig.json',
bundle: true,
minify: isProduction,
minifyIdentifiers: false,
sourcemap: false,
outfile: `./build/${appName}/theme/${themeName}.js`,
plugins: [
// fileLoaderPlugin({ out: prefix }),
sassPlugin({
type: 'css',
silenceDeprecations: ['import'],
logger: {
warn: (msg) => console.warn(msg),
debug: () => { },
}
}),
],
color: true,
logLevel: 'info',
define: {
'process.env.NODE_ENV': JSON.stringify(NODE_ENV_PRD ? 'production' : 'development'),
'process.env.DEBUG': JSON.stringify(process.env.DEBUG || false),
},
});
await ctx.rebuild();
if (!isProduction) await ctx.watch();
}
function findBrowserTests(names) {
const dir = path.resolve('./src', 'tests', 'browser');
let files = fs.readdirSync(dir).filter(file => file.endsWith('.ts')).map(file => file.replace('.ts', ''));
if (names.length) {
files = files.filter(file => names.includes(file));
}
return files.map(name => ({ kind: 'browser-test', name }));
}
const argParser = new argparse.ArgumentParser({
add_help: true,
description: 'Mol* Build'
});
argParser.add_argument('--prd', {
help: 'Create a production build.',
required: false,
action: 'store_true',
});
argParser.add_argument('--no-src-map', {
help: 'Do not include source map.',
required: false,
action: 'store_true',
});
argParser.add_argument('--apps', '-a', {
help: 'Apps to build.',
required: false,
nargs: '*',
});
argParser.add_argument('--examples', '-e', {
help: 'Examples to build.',
required: false,
nargs: '*',
});
argParser.add_argument('--browser-tests', '-bt', {
help: 'Browser Tests to build.',
required: false,
nargs: '*',
});
argParser.add_argument('--port', '-p', {
help: 'Port.',
required: false,
default: 1338,
type: 'int',
});
argParser.add_argument('--host', {
help: 'Show all available host addresses.',
required: false,
action: 'store_true',
});
const args = argParser.parse_args();
const isProduction = !!args.prd;
const includeSourceMap = !args.no_src_map;
const NODE_ENV_PRD = isProduction || process.env.NODE_ENV === 'production';
const VERSION = isProduction ? JSON.parse(fs.readFileSync('./package.json', 'utf8')).version : '(dev build)';
const TIMESTAMP = Date.now();
const apps = (!args.apps ? [] : (args.apps.length ? args.apps.map(a => findApp(a, 'app')).filter(a => a) : Apps.filter(a => a.kind === 'app')));
const examples = (!args.examples ? [] : (args.examples.length ? args.examples.map(e => findApp(e, 'example')).filter(a => a) : Apps.filter(a => a.kind === 'example')));
const browserTests = (!args.browser_tests ? [] : findBrowserTests(args.browser_tests));
console.log('Apps:', apps.map(a => a.name));
console.log('Examples:', examples.map(e => e.name));
console.log('Browser Tests', browserTests.map(e => e.name));
console.log('');
function getLocalIPs() {
const interfaces = os.networkInterfaces();
const ips = [];
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
// Skip internal and non-IPv4 addresses
if (iface.internal || iface.family !== 'IPv4') continue;
ips.push(iface.address);
}
}
return ips;
}
async function main() {
const promises = [];
console.log(isProduction ? 'Building apps...' : 'Initial build...');
for (const app of apps) {
promises.push(createBundle(app));
if (app.themes) {
for (const theme of app.themes) {
promises.push(createTheme(app.name, theme));
}
}
}
for (const example of examples) promises.push(createBundle(example));
for (const browserTest of browserTests) promises.push(createBundle(browserTest));
await Promise.all(promises);
if (isProduction) {
console.log('Done.');
process.exit(0);
}
console.log('Initial build complete.');
const certfile = './dev.pem';
const keyfile = './dev-key.pem';
const sslEnabled = fs.existsSync(certfile) && fs.existsSync(keyfile);
const protocol = sslEnabled ? 'https' : 'http';
const ctx = await esbuild.context({});
ctx.serve({
servedir: './',
port: args.port,
host: '0.0.0.0', // Always listen on all interfaces
certfile: sslEnabled ? certfile : undefined,
keyfile: sslEnabled ? keyfile : undefined,
});
console.log('');
console.log(`Server URL: ${protocol}://localhost:${args.port}`);
if (args.host) {
console.log('Available host addresses:');
const ips = getLocalIPs();
ips.forEach(ip => console.log(` ${protocol}://${ip}:${args.port}`));
}
console.log('');
console.log('Watching for changes...');
console.log('');
console.log('Press Ctrl+C to stop.');
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -6,6 +6,7 @@
const fs = require('fs');
const path = require('path');
const argparse = require('argparse');
function removeDir(dirPath) {
for (const ent of fs.readdirSync(dirPath)) {
@@ -24,11 +25,29 @@ function remove(entryPath) {
fs.unlinkSync(entryPath);
}
const toClean = [
path.resolve(__dirname, '../build'),
path.resolve(__dirname, '../lib'),
path.resolve(__dirname, '../tsconfig.tsbuildinfo'),
];
const argParser = new argparse.ArgumentParser({
add_help: true,
description: 'Clean Script'
});
argParser.add_argument('--build', { required: false, action: 'store_true' });
argParser.add_argument('--lib', { required: false, action: 'store_true' });
argParser.add_argument('--all', { required: false, action: 'store_true' });
const args = argParser.parse_args();
const toClean = [];
if (args.build || args.all) {
toClean.push(path.resolve(__dirname, '../build'));
toClean.push(path.resolve(__dirname, '../deploy/data'));
}
if (args.lib || args.all) {
toClean.push(
path.resolve(__dirname, '../lib'),
path.resolve(__dirname, '../tsconfig.tsbuildinfo'),
);
}
console.log('\n###', 'cleaning', toClean.join(', '));
toClean.forEach(ph => {
if (fs.existsSync(ph)) {

View File

@@ -1,22 +1,35 @@
/**
* Copyright (c) 2019-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
const git = require('simple-git');
const path = require('path');
const fs = require("fs");
const fse = require("fs-extra");
const fs = require('fs');
const fse = require('fs-extra');
const argparse = require('argparse');
const remoteUrl = "https://github.com/molstar/molstar.github.io.git";
const VERSION = require(path.resolve(__dirname, '../package.json')).version;
const MVS_STORIES_VERSION = require(path.resolve(__dirname, '../src/apps/mvs-stories/version.ts')).VERSION;
const remoteUrl = 'https://github.com/molstar/molstar.github.io.git';
const dataDir = path.resolve(__dirname, '../data/');
const buildDir = path.resolve(__dirname, '../build/');
const deployDir = path.resolve(buildDir, 'deploy/');
const localPath = path.resolve(deployDir, 'molstar.github.io/');
const deployDir = path.resolve(__dirname, '../deploy/');
const localPath = path.resolve(deployDir, 'data/');
const repositoryPath = path.resolve(deployDir, 'molstar.github.io/');
const analyticsTag = /<!-- __MOLSTAR_ANALYTICS__ -->/g;
const analyticsCode = `<!-- Cloudflare Web Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "c414cbae2d284ea995171a81e4a3e721"}'></script><!-- End Cloudflare Web Analytics --><iframe src="https://web3dsurvey.com/collector-iframe.html" style="width: 1px; height: 1px;"></iframe>`;
const manifestTag = /<!-- __MOLSTAR_MANIFEST__ -->/g;
const manifestCode = `<link rel="manifest" href="./manifest.webmanifest">`;
const pwaTag = /<!-- __MOLSTAR_PWA__ -->/g;
const pwaCode = `<script src='./pwa.js'></script>`;
function log(command, stdout, stderr) {
if (command) {
console.log('\n###', command);
@@ -31,70 +44,146 @@ function addAnalytics(path) {
fs.writeFileSync(path, result, 'utf8');
}
function addManifest(path) {
const data = fs.readFileSync(path, 'utf8');
const result = data.replace(manifestTag, manifestCode);
fs.writeFileSync(path, result, 'utf8');
}
function addPwa(path) {
const data = fs.readFileSync(path, 'utf8');
const result = data.replace(pwaTag, pwaCode);
fs.writeFileSync(path, result, 'utf8');
}
function addVersion(path) {
const data = fs.readFileSync(path, 'utf8');
const result = data.replace('__MOLSTAR_VERSION__', VERSION);
fs.writeFileSync(path, result, 'utf8');
}
function copyViewer() {
console.log('\n###', 'copy viewer files');
const viewerBuildPath = path.resolve(buildDir, '../build/viewer/');
const viewerBuildPath = path.resolve(buildDir, 'viewer/');
const viewerDeployPath = path.resolve(localPath, 'viewer/');
fse.copySync(viewerBuildPath, viewerDeployPath, { overwrite: true });
addAnalytics(path.resolve(viewerDeployPath, 'index.html'));
addManifest(path.resolve(viewerDeployPath, 'index.html'));
addPwa(path.resolve(viewerDeployPath, 'index.html'));
const pwaDataPath = path.resolve(dataDir, 'pwa/');
fse.copySync(pwaDataPath, viewerDeployPath, { overwrite: true });
addVersion(path.resolve(viewerDeployPath, 'sw.js'));
}
function copyMe() {
console.log('\n###', 'copy me files');
const meBuildPath = path.resolve(buildDir, '../build/mesoscale-explorer/');
const meBuildPath = path.resolve(buildDir, 'mesoscale-explorer/');
const meDeployPath = path.resolve(localPath, 'me/viewer/');
fse.copySync(meBuildPath, meDeployPath, { overwrite: true });
addAnalytics(path.resolve(meDeployPath, 'index.html'));
}
function copyMVSStories() {
console.log('\n###', 'copy MVS stories files');
const mvsStoriesBuildPath = path.resolve(buildDir, 'mvs-stories/');
const mvsStoriesDeployPath = path.resolve(localPath, `stories-viewer/v${MVS_STORIES_VERSION}/`);
fse.copySync(mvsStoriesBuildPath, mvsStoriesDeployPath, { overwrite: true });
addAnalytics(path.resolve(mvsStoriesDeployPath, 'index.html'));
// TODO: add PWA
// addManifest(path.resolve(mvsStoriesDeployPath, 'index.html'));
// addPwa(path.resolve(mvsStoriesDeployPath, 'index.html'));
}
function copyDemo(name) {
console.log('\n###', `copy demo files for ${name}`);
const demoBuildPath = path.resolve(buildDir, `examples/${name}/`);
const demoDeployPath = path.resolve(localPath, `demos/${name}/`);
fse.copySync(demoBuildPath, demoDeployPath, { overwrite: true });
addAnalytics(path.resolve(demoDeployPath, 'index.html'));
}
function copyDemos() {
console.log('\n###', 'copy demos files');
const lightingBuildPath = path.resolve(buildDir, '../build/examples/lighting/');
const lightingDeployPath = path.resolve(localPath, 'demos/lighting/');
fse.copySync(lightingBuildPath, lightingDeployPath, { overwrite: true });
addAnalytics(path.resolve(lightingDeployPath, 'index.html'));
const orbitalsBuildPath = path.resolve(buildDir, '../build/examples/alpha-orbitals/');
const orbitalsDeployPath = path.resolve(localPath, 'demos/alpha-orbitals/');
fse.copySync(orbitalsBuildPath, orbitalsDeployPath, { overwrite: true });
addAnalytics(path.resolve(orbitalsDeployPath, 'index.html'));
copyDemo('lighting');
copyDemo('alpha-orbitals');
copyDemo('mvs-stories');
}
function copyFiles() {
try {
copyViewer();
copyMe();
copyMVSStories();
copyDemos();
} catch (e) {
console.error(e);
}
}
function copyToRepository() {
console.log('\n###', 'copy repository files');
fse.copySync(localPath, repositoryPath, { overwrite: true });
}
function syncRepository() {
console.log('\n###', 'sync repository');
if (!fs.existsSync(path.resolve(repositoryPath, '.git/'))) {
console.log('\n###', 'clone repository');
git()
.outputHandler(log)
.clone(remoteUrl, repositoryPath)
.fetch(['--all'])
.exec(copyToRepository);
} else {
console.log('\n###', 'update repository');
git()
.outputHandler(log)
.fetch(['--all'])
.reset(['--hard', 'origin/master'])
.exec(copyToRepository);
}
}
function commit() {
console.log('\n###', 'commit changes');
git()
.outputHandler(log)
.add(['-A'])
.commit(`Updated Apps and Demos
- Mol* version: ${VERSION}
- MVS Stories version: ${MVS_STORIES_VERSION}`)
.push();
}
if (!fs.existsSync(localPath)) {
console.log('\n###', 'create localPath');
fs.mkdirSync(localPath, { recursive: true });
}
process.chdir(localPath);
const argParser = new argparse.ArgumentParser({
add_help: true,
description: 'Mol* Deploy'
});
argParser.add_argument('--local',{
help: 'Do not commit to remote repository.',
required: false,
action: 'store_true',
});
const args = argParser.parse_args();
if (!fs.existsSync(path.resolve(localPath, '.git/'))) {
console.log('\n###', 'clone repository');
git()
.outputHandler(log)
.clone(remoteUrl, localPath)
.fetch(['--all'])
.exec(copyFiles)
.add(['-A'])
.commit('updated viewer & demos')
.push();
} else {
console.log('\n###', 'update repository');
git()
.outputHandler(log)
.fetch(['--all'])
.reset(['--hard', 'origin/master'])
.exec(copyFiles)
.add(['-A'])
.commit('updated viewer & demos')
.push();
}
copyFiles();
if (args.local) {
process.exit(0);
}
if (!fs.existsSync(repositoryPath)) {
console.log('\n###', 'create repositoryPath');
fs.mkdirSync(repositoryPath, { recursive: true });
}
process.chdir(repositoryPath);
syncRepository();
commit();

16
scripts/write-version.mjs Normal file
View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import * as fs from 'fs';
const VERSION = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version;
const TIMESTAMP = Date.now();
const file = `export var PLUGIN_VERSION = '${VERSION}';\nexport var PLUGIN_VERSION_DATE = new Date(${TIMESTAMP})`;
const files = ['./lib/mol-plugin/version.js', './lib/commonjs/mol-plugin/version.js'];
for (const f of files) {
if (!fs.existsSync(f)) continue;
fs.writeFileSync(f, file);
}

View File

@@ -27,7 +27,7 @@ import { ObjectKeys } from '../../mol-util/type-helpers';
import './index.html';
import { ShowButtons, StructurePreset, ViewportComponent } from './viewport';
require('mol-plugin-ui/skin/light.scss');
import '../../mol-plugin-ui/skin/light.scss';
export { PLUGIN_VERSION as version } from '../../mol-plugin/version';
export { setDebugMode, setProductionMode } from '../../mol-util/debug';

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2022-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -25,7 +25,7 @@ import { MesoFocusLoci } from './behavior/camera';
import { GraphicsMode, MesoscaleState } from './data/state';
import { MesoSelectLoci } from './behavior/select';
import { Transparency } from '../../mol-gl/webgl/render-item';
import { LoadModel, loadExampleEntry, loadPdb, loadPdbDev, loadUrl, openState } from './ui/states';
import { LoadModel, loadExampleEntry, loadPdb, loadPdbIhm, loadUrl, openState } from './ui/states';
import { Asset } from '../../mol-util/assets';
import { AnimateCameraSpin } from '../../mol-plugin-state/animation/built-in/camera-spin';
import { AnimateCameraRock } from '../../mol-plugin-state/animation/built-in/camera-rock';
@@ -85,7 +85,7 @@ const DefaultMesoscaleExplorerOptions = {
viewportShowExpand: PluginConfig.Viewport.ShowExpand.defaultValue,
viewportShowControls: PluginConfig.Viewport.ShowControls.defaultValue,
viewportShowSettings: PluginConfig.Viewport.ShowSettings.defaultValue,
viewportShowSelectionMode: false,
viewportShowSelectionMode: true,
viewportShowAnimation: false,
viewportShowTrajectoryControls: false,
pluginStateServer: PluginConfig.State.DefaultServer.defaultValue,
@@ -120,8 +120,15 @@ export class MesoscaleExplorer {
await loadPdb(this.plugin, id);
}
/**
* @deprecated Scheduled for removal in v5. Use {@link loadPdbIhm | loadPdbIhm(id: string)} instead.
*/
async loadPdbDev(id: string) {
await loadPdbDev(this.plugin, id);
await this.loadPdbIhm(id);
}
async loadPdbIhm(id: string) {
await loadPdbIhm(this.plugin, id);
}
static async create(elementOrId: string | HTMLElement, options: Partial<MesoscaleExplorerOptions> = {}) {
@@ -140,10 +147,11 @@ export class MesoscaleExplorer {
behaviors: [
PluginSpec.Behavior(PluginBehaviors.Camera.CameraAxisHelper),
PluginSpec.Behavior(PluginBehaviors.Camera.CameraControls),
PluginSpec.Behavior(PluginBehaviors.State.SnapshotControls),
PluginSpec.Behavior(MesoFocusLoci),
PluginSpec.Behavior(MesoSelectLoci),
PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
...o.extensions.map(e => Extensions[e]),
],
animations: [
@@ -245,6 +253,10 @@ export class MesoscaleExplorer {
},
cameraFog: { name: 'off', params: {} },
hiZ: { enabled: true },
xr: {
disablePostprocessing: false,
sceneRadiusInMeters: 0.75,
},
});
plugin.representation.structure.registry.clear();
@@ -254,7 +266,6 @@ export class MesoscaleExplorer {
image: true,
componentManager: false,
structureSelection: true,
behavior: true,
});
plugin.managers.lociLabels.clearProviders();

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2023-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -21,6 +21,7 @@ const Key = Binding.TriggerKey;
const DefaultMesoFocusLociBindings = {
clickCenter: Binding([
Trigger(B.Flag.Primary, M.create()),
Trigger(B.Flag.Trigger),
], 'Camera center', 'Click element using ${triggers}'),
clickCenterFocus: Binding([
Trigger(B.Flag.Secondary, M.create()),

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2023-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -24,7 +24,8 @@ const Trigger = Binding.Trigger;
const DefaultMesoSelectLociBindings = {
click: Binding([
Trigger(B.Flag.Primary, M.create())
Trigger(B.Flag.Primary, M.create()),
Trigger(B.Flag.Trigger),
], 'Click', 'Click element using ${triggers}'),
clickToggleSelect: Binding([
Trigger(B.Flag.Primary, M.create({ shift: true })),
@@ -73,7 +74,7 @@ export const MesoSelectLoci = PluginBehavior.create<MesoSelectLociProps>({
this.ctx.managers.interactivity.lociSelects.deselectAll();
return;
}
const loci = Loci.normalize(current.loci, modifiers.control ? 'entity' : 'chain');
const loci = Loci.normalize(current.loci, modifiers.control ? 'entity' : this.ctx.managers.interactivity.props.granularity);
this.ctx.managers.interactivity.lociSelects.toggle({ loci }, false);
if (StructureElement.Loci.is(current.loci)) {
const cell = this.ctx.helpers.substructureParent.get(current.loci.structure);
@@ -116,7 +117,7 @@ export const MesoSelectLoci = PluginBehavior.create<MesoSelectLociProps>({
if (modifiers.control) {
this.ctx.managers.interactivity.lociHighlights.highlightOnly({ repr: current.repr, loci: EveryLoci }, false);
} else {
const loci = Loci.normalize(current.loci, 'chain');
const loci = Loci.normalize(current.loci, this.ctx.managers.interactivity.props.granularity);
this.ctx.managers.interactivity.lociHighlights.highlightOnly({ repr: current.repr, loci }, false);
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Ludovic Autin <ludovic.autin@gmail.com>
@@ -36,6 +36,12 @@ function getSpacefillParams(color: Color, sizeFactor: number, graphics: Graphics
approximate: gmp.approximate,
alphaThickness: gmp.alphaThickness,
visuals: [merge ? 'structure-element-sphere' : 'element-sphere'],
interior: {
color: Color.fromNormalizedRgb(0, 0, 0),
colorStrength: 0.15,
substance: { metalness: 0.0, roughness: 1.0, bumpiness: 0.0 },
substanceStrength: 1,
}
},
},
colorTheme: {
@@ -49,7 +55,7 @@ function getSpacefillParams(color: Color, sizeFactor: number, graphics: Graphics
sizeTheme: {
name: 'physical',
params: {
value: 1,
scale: 1,
}
},
};

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2023-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -50,6 +50,12 @@ function getSpacefillParams(color: Color, sizeFactor: number, graphics: Graphics
clipPrimitive: true,
approximate: gmp.approximate,
alphaThickness: gmp.alphaThickness,
interior: {
color: Color.fromNormalizedRgb(0, 0, 0),
colorStrength: 0.15,
substance: { metalness: 0.0, roughness: 1.0, bumpiness: 0.0 },
substanceStrength: 1,
}
},
},
colorTheme: {
@@ -192,12 +198,13 @@ export async function createGenericHierarchy(plugin: PluginContext, file: Asset.
const t = isBinary ? d : utf8Read(d, 0, d.length);
const file = Asset.File(new File([t], ent.file));
const color = ColorNames.skyblue;
const color = (ent.color) ? Color.fromRgb(ent.color[0], ent.color[1], ent.color[2]) : ColorNames.skyblue;
const sizeFactor = ent.sizeFactor || 1;
const tags = ent.groups.map(({ id, root }) => `${root}:${id}`);
const instances = ent.instances && getAssetInstances(ent.instances);
const description = ent.description;
const label = ent.label || ent.file.split('.')[0];
build = build
.toRoot()
@@ -300,6 +307,7 @@ type GenericEntity = {
file: string
label?: string
description?: string
color?: number[]
groups: {
/** reference to `${GenericGroup.id}` */
id: string,

View File

@@ -1,10 +1,11 @@
/**
* Copyright (c) 2023-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2023-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { MmcifFormat } from '../../../../mol-model-formats/structure/mmcif';
import { Model } from '../../../../mol-model/structure/model/model';
import { PluginStateObject } from '../../../../mol-plugin-state/objects';
import { StructureRepresentation3D } from '../../../../mol-plugin-state/transforms/representation';
import { PluginContext } from '../../../../mol-plugin/context';
@@ -40,6 +41,12 @@ function getSpacefillParams(color: Color, scaleFactor: number, graphics: Graphic
clipPrimitive: true,
approximate: gmp.approximate,
alphaThickness: gmp.alphaThickness,
interior: {
color: Color.fromNormalizedRgb(0, 0, 0),
colorStrength: 0.15,
substance: { metalness: 0.0, roughness: 1.0, bumpiness: 0.0 },
substanceStrength: 1,
}
},
},
colorTheme: {
@@ -53,7 +60,7 @@ function getSpacefillParams(color: Color, scaleFactor: number, graphics: Graphic
sizeTheme: {
name: 'physical',
params: {
value: 1,
scale: scaleFactor,
}
},
};
@@ -96,6 +103,8 @@ export async function createMmcifHierarchy(plugin: PluginContext, trajectory: St
});
}
const coarseGrained = Model.isCoarseGrained(model.data!);
const entGroups = new Map<string, StateObjectSelector>();
const entIds = new Map<string, { idx: number, members: Map<number, number> }>();
const entColors = new Map<string, Color[]>();
@@ -164,7 +173,7 @@ export async function createMmcifHierarchy(plugin: PluginContext, trajectory: St
for (let i = 0; i < entities._rowCount; i++) {
const t = getEntityType(i);
const color = entColors.get(t)![entIds.get(t)!.members.get(i)!];
const scaleFactor = spheresAvgRadius.get(entities.id.value(i)) || 1;
const scaleFactor = spheresAvgRadius.get(entities.id.value(i)) || (coarseGrained ? 2 : 1);
build = build
.toRoot()

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2022-2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -35,6 +35,12 @@ function getSpacefillParams(color: Color, graphics: GraphicsMode) {
clipPrimitive: true,
approximate: gmp.approximate,
alphaThickness: gmp.alphaThickness,
interior: {
color: Color.fromNormalizedRgb(0, 0, 0),
colorStrength: 0.15,
substance: { metalness: 0.0, roughness: 1.0, bumpiness: 0.0 },
substanceStrength: 1,
}
},
},
colorTheme: {

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2023-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2023-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -10,9 +10,10 @@ import { ParamDefinition as PD } from '../../../mol-util/param-definition';
import { Task } from '../../../mol-task';
import { Color } from '../../../mol-util/color';
import { Spheres } from '../../../mol-geo/geometry/spheres/spheres';
import { getAnimationParam } from '../../../mol-geo/geometry/animation';
import { Clip } from '../../../mol-util/clip';
import { escapeRegExp, stringToWords } from '../../../mol-util/string';
import { Vec3 } from '../../../mol-math/linear-algebra';
import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
import { ParamMapping } from '../../../mol-util/param-mapping';
import { EntityNode } from '../ui/entities';
import { DistinctColorsProps, distinctColors } from '../../../mol-util/color/distinct';
@@ -21,10 +22,10 @@ import { Hcl } from '../../../mol-util/color/spaces/hcl';
import { StateObjectCell, StateObjectRef, StateSelection } from '../../../mol-state';
import { ShapeRepresentation3D, StructureRepresentation3D } from '../../../mol-plugin-state/transforms/representation';
import { SpacefillRepresentationProvider } from '../../../mol-repr/structure/representation/spacefill';
import { assertUnreachable } from '../../../mol-util/type-helpers';
import { MesoscaleExplorerState } from '../app';
import { saturate } from '../../../mol-math/interpolate';
import { Material } from '../../../mol-util/material';
import { PCG } from '../../../mol-data/util/hash-functions';
function getHueRange(hue: number, variability: number) {
let min = hue - variability;
@@ -37,10 +38,11 @@ function getHueRange(hue: number, variability: number) {
function getGrayscaleColors(count: number, luminance: number, variability: number) {
const out: Color[] = [];
const pcg = new PCG();
for (let i = 0; i < count; ++ i) {
const l = saturate(luminance / 100);
const v = saturate(variability / 180) * Math.random();
const s = Math.random() > 0.5 ? 1 : -1;
const v = saturate(variability / 180) * pcg.float();
const s = pcg.float() > 0.5 ? 1 : -1;
const d = Math.abs(l + s * v) % 1;
out[i] = Color.fromNormalizedRgb(d, d, d);
}
@@ -172,6 +174,8 @@ export const LodParams = {
approximate: Spheres.Params.approximate,
};
export const AnimationParams = getAnimationParam().params;
export const SimpleClipParams = {
type: PD.Select('none', PD.objectToOptions(Clip.Type, t => stringToWords(t))),
invert: PD.Boolean(false),
@@ -211,7 +215,8 @@ export function getClipObjects(values: SimpleClipProps, boundingSphere: Sphere3D
invert: values.invert,
position,
scale,
rotation: values.rotation
rotation: values.rotation,
transform: Mat4.identity(),
}];
}
@@ -278,6 +283,7 @@ export const MesoscaleGroupParams = {
emissive: PD.Numeric(0, { min: 0, max: 1, step: 0.01 }),
lod: PD.Group(LodParams),
clip: PD.Group(SimpleClipParams),
animation: PD.Group(AnimationParams),
};
export type MesoscaleGroupProps = PD.Values<typeof MesoscaleGroupParams>;
@@ -315,38 +321,7 @@ export function getMesoscaleGroupParams(graphicsMode: GraphicsMode): MesoscaleGr
export type LodLevels = typeof SpacefillRepresentationProvider.defaultValues['lodLevels']
export function getLodLevels(graphicsMode: Exclude<GraphicsMode, 'custom'>): LodLevels {
switch (graphicsMode) {
case 'performance':
return [
{ minDistance: 1, maxDistance: 300, overlap: 0, stride: 1, scaleBias: 1 },
{ minDistance: 300, maxDistance: 2000, overlap: 0, stride: 40, scaleBias: 3 },
{ minDistance: 2000, maxDistance: 6000, overlap: 0, stride: 150, scaleBias: 3 },
{ minDistance: 6000, maxDistance: 10000000, overlap: 0, stride: 300, scaleBias: 2.5 },
];
case 'balanced':
return [
{ minDistance: 1, maxDistance: 500, overlap: 0, stride: 1, scaleBias: 1 },
{ minDistance: 500, maxDistance: 2000, overlap: 0, stride: 15, scaleBias: 3 },
{ minDistance: 2000, maxDistance: 6000, overlap: 0, stride: 70, scaleBias: 2.7 },
{ minDistance: 6000, maxDistance: 10000000, overlap: 0, stride: 200, scaleBias: 2.5 },
];
case 'quality':
return [
{ minDistance: 1, maxDistance: 1000, overlap: 0, stride: 1, scaleBias: 1 },
{ minDistance: 1000, maxDistance: 4000, overlap: 0, stride: 10, scaleBias: 3 },
{ minDistance: 4000, maxDistance: 10000, overlap: 0, stride: 50, scaleBias: 2.7 },
{ minDistance: 10000, maxDistance: 10000000, overlap: 0, stride: 200, scaleBias: 2.3 },
];
case 'ultra':
return [
{ minDistance: 1, maxDistance: 5000, overlap: 0, stride: 1, scaleBias: 1 },
{ minDistance: 5000, maxDistance: 10000, overlap: 0, stride: 10, scaleBias: 3 },
{ minDistance: 10000, maxDistance: 30000, overlap: 0, stride: 50, scaleBias: 2.5 },
{ minDistance: 30000, maxDistance: 10000000, overlap: 0, stride: 200, scaleBias: 2 },
];
default:
assertUnreachable(graphicsMode);
}
return Spheres.LodLevelsPresets[graphicsMode];
}
export type GraphicsMode = 'ultra' | 'quality' | 'balanced' | 'performance' | 'custom';

View File

@@ -93,9 +93,15 @@
return;
}
var pdbihm = getParam('pdbihm', '[^&]+').trim();
if (pdbihm) {
me.loadPdbIhm(pdbihm);
return;
}
// support for deprecated pdb-dev param
var pdbdev = getParam('pdbdev', '[^&]+').trim();
if (pdbdev) {
me.loadPdbDev(pdbdev);
me.loadPdbIhm(pdbdev);
return;
}
window.addEventListener('unload', () => {

View File

@@ -6,5 +6,5 @@
import './favicon.ico';
import './index.html';
require('./style.scss');
import './style.scss';
export * from './app';

View File

@@ -1,32 +1,28 @@
@use "sass:color";
$default-background: #2D3E50;
$font-color: #EDF1F2;
$hover-font-color: #3B9AD9;
$entity-current-font-color: #FFFFFF;
$msp-btn-remove-background: #BF3A31;
$msp-btn-remove-hover-font-color:#ffffff;
$msp-btn-commit-on-font-color: #ffffff;
$entity-badge-font-color: #ccd4e0;
@use '../../mol-plugin-ui/skin/base/colors' with (
$default-background: #2D3E50,
$font-color: #EDF1F2,
$hover-font-color: #3B9AD9,
$entity-current-font-color: #FFFFFF,
$msp-btn-remove-background: #BF3A31,
$msp-btn-remove-hover-font-color:#ffffff,
$msp-btn-commit-on-font-color: #ffffff,
$entity-badge-font-color: #ccd4e0,
// used in LOG
$log-message: #0CCA5D;
$log-info: #5E3673;
$log-warning: #FCC937;
$log-error: #FD354B;
// used in LOG
$log-message: #0CCA5D,
$log-info: #5E3673,
$log-warning: #FCC937,
$log-error: #FD354B,
$logo-background: rgba(0,0,0,0.75);
$logo-background: rgba(0,0,0,0.75),
@function color-lower-contrast($color, $amount) {
@return color.adjust($color, $lightness: -$amount, $space: hsl);
}
$color-adjust-sign: -1,
);
@function color-increase-contrast($color, $amount) {
@return color.adjust($color, $lightness: $amount, $space: hsl);
}
@import 'mol-plugin-ui/skin/base/base';
@import 'mol-plugin-ui/skin/base/variables';
@use '../../mol-plugin-ui/skin/base/base';
@use '../../mol-plugin-ui/skin/base/vars' as *;
a {
color: $font-color;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2022-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -18,7 +18,7 @@ import { CombinedColorControl } from '../../../mol-plugin-ui/controls/color';
import { MarkerAction } from '../../../mol-util/marker-action';
import { EveryLoci, Loci } from '../../../mol-model/loci';
import { deepEqual } from '../../../mol-util';
import { ColorValueParam, ColorParams, ColorProps, DimLightness, LightnessParams, LodParams, MesoscaleGroup, MesoscaleGroupProps, OpacityParams, SimpleClipParams, SimpleClipProps, createClipMapping, getClipObjects, getDistinctGroupColors, RootParams, MesoscaleState, getRoots, getAllGroups, getAllLeafGroups, getFilteredEntities, getAllFilteredEntities, getGroups, getEntities, getAllEntities, getEntityLabel, updateColors, getGraphicsModeProps, GraphicsMode, MesoscaleStateParams, setGraphicsCanvas3DProps, PatternParams, expandAllGroups, EmissiveParams, IllustrativeParams, getCellDescription, getEntityDescription, getEveryEntity } from '../data/state';
import { ColorValueParam, ColorParams, ColorProps, DimLightness, LightnessParams, LodParams, AnimationParams, MesoscaleGroup, MesoscaleGroupProps, OpacityParams, SimpleClipParams, SimpleClipProps, createClipMapping, getClipObjects, getDistinctGroupColors, RootParams, MesoscaleState, getRoots, getAllGroups, getAllLeafGroups, getFilteredEntities, getAllFilteredEntities, getGroups, getEntities, getAllEntities, getEntityLabel, updateColors, getGraphicsModeProps, GraphicsMode, MesoscaleStateParams, setGraphicsCanvas3DProps, PatternParams, expandAllGroups, EmissiveParams, IllustrativeParams, getCellDescription, getEntityDescription, getEveryEntity } from '../data/state';
import React, { useState } from 'react';
import { MesoscaleExplorerState } from '../app';
import { StructureElement } from '../../../mol-model/structure/structure/element';
@@ -29,6 +29,7 @@ import { Sphere3D } from '../../../mol-math/geometry';
import { MesoFocusLoci } from '../behavior/camera';
import Markdown from 'react-markdown';
import { combineLatest } from 'rxjs';
import { ColorLoaderControls } from './states';
function centerLoci(plugin: PluginContext, loci: Loci, durationMs = 250) {
const { canvas3d } = plugin;
@@ -619,6 +620,7 @@ class Node<P extends {}, S extends { isDisabled: boolean }> extends PluginUIComp
}
}
export class GroupNode extends Node<{ filter: string }, { isCollapsed: boolean, action?: 'color' | 'clip' | 'root', isDisabled: boolean }> {
state = {
isCollapsed: !!this.props.cell.state.isCollapsed,
@@ -826,6 +828,26 @@ export class GroupNode extends Node<{ filter: string }, { isCollapsed: boolean,
update.commit();
};
updateAnimation = (values: PD.Values) => {
const update = this.plugin.state.data.build();
for (const r of this.allFilteredEntities) {
update.to(r).update(old => {
if (old.type) {
old.type.params.animation = values;
}
});
}
for (const g of this.allGroups) {
update.to(g).update(old => {
old.animation = values;
});
}
update.commit();
};
update = (props: MesoscaleGroupProps) => {
this.plugin.state.data.build().to(this.ref).update(props);
};
@@ -863,6 +885,7 @@ export class GroupNode extends Node<{ filter: string }, { isCollapsed: boolean,
const rootValue = this.cell.params?.values.color;
const clipValue = this.cell.params?.values.clip;
const lodValue = this.cell.params?.values.lod;
const animationValue = this.cell.params?.values.animation;
const isRoot = this.cell.params?.values.root;
const groups = this.groups;
@@ -881,12 +904,13 @@ export class GroupNode extends Node<{ filter: string }, { isCollapsed: boolean,
const root = (isRoot && this.allGroups.length > 1) && <IconButton svg={BrushSvg} toggleState={false} disabled={disabled} small onClick={this.toggleRoot} />;
const clip = <IconButton svg={ContentCutSvg} toggleState={false} disabled={disabled} small onClick={this.toggleClip} />;
const visibility = <IconButton svg={state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} disabled={disabled} small onClick={this.toggleVisible} />;
const loadColorButton = (depth === 0) && <ColorLoaderControls plugin={this.plugin} />;
return <>
<div className={`msp-flex-row`} style={{ margin: `1px 5px 1px ${depth * 10 + 5}px` }}>
{expand}
{label}
{root || color}
{loadColorButton}
{clip}
{visibility}
</div>
@@ -901,6 +925,7 @@ export class GroupNode extends Node<{ filter: string }, { isCollapsed: boolean,
topRightIcon={CloseSvg} noTopMargin childrenClassName='msp-viewport-controls-panel-controls'>
<ParameterControls params={SimpleClipParams} values={clipValue} onChangeValues={this.updateClip} />
<ParameterControls params={LodParams} values={lodValue} onChangeValues={this.updateLod} />
<ParameterControls params={AnimationParams} values={animationValue} onChangeValues={this.updateAnimation} />
</ControlGroup>
</div>}
{this.state.action === 'root' && <div style={{ marginRight: 5 }} className='msp-accent-offset'>
@@ -1077,6 +1102,19 @@ export class EntityNode extends Node<{}, { action?: 'color' | 'clip', isDisabled
};
}
get animationValue(): PD.Values<typeof AnimationParams> | undefined {
const p = this.cell.transform.params?.type?.params?.animation;
if (!p) return;
return {
wiggleMode: p.wiggleMode,
wiggleSpeed: p.wiggleSpeed,
wiggleAmplitude: p.wiggleAmplitude,
wiggleFrequency: p.wiggleFrequency,
tumbleSpeed: p.tumbleSpeed,
tumbleAmplitude: p.tumbleAmplitude,
};
}
get patternValue(): { amplitude: number, frequency: number } | undefined {
const p = this.cell.transform.params;
if (p.type) return;
@@ -1191,6 +1229,15 @@ export class EntityNode extends Node<{}, { action?: 'color' | 'clip', isDisabled
}
};
updateAnimation = (values: PD.Values) => {
const params = this.cell.transform.params as StateTransformer.Params<StructureRepresentation3D>;
if (!params.type) return;
this.plugin.build().to(this.ref).update(old => {
old.type.params.animation = values;
}).commit();
};
updatePattern = (values: PD.Values) => {
return this.plugin.build().to(this.ref).update(old => {
if (!old.type) {
@@ -1210,6 +1257,7 @@ export class EntityNode extends Node<{}, { action?: 'color' | 'clip', isDisabled
const opacityValue = this.opacityValue;
const emissiveValue = this.emissiveValue;
const lodValue = this.lodValue;
const animationValue = this.animationValue;
const patternValue = this.patternValue;
const l = getEntityLabel(this.plugin, this.cell);
@@ -1248,6 +1296,7 @@ export class EntityNode extends Node<{}, { action?: 'color' | 'clip', isDisabled
topRightIcon={CloseSvg} noTopMargin childrenClassName='msp-viewport-controls-panel-controls'>
<ParameterMappingControl mapping={this.clipMapping} />
{lodValue && <ParameterControls params={LodParams} values={lodValue} onChangeValues={this.updateLod} />}
{animationValue && <ParameterControls params={AnimationParams} values={animationValue} onChangeValues={this.updateAnimation} />}
</ControlGroup>
</div>}
</>;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2022-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -13,17 +13,19 @@ import { StructureMeasurementsControls } from '../../../mol-plugin-ui/structure/
import { MesoscaleExplorerState } from '../app';
import { MesoscaleState } from '../data/state';
import { EntityControls, FocusInfo, ModelInfo, SelectionInfo } from './entities';
import { LoaderControls, ExampleControls, SessionControls, SnapshotControls, DatabaseControls, MesoQuickStylesControls, ExplorerInfo } from './states';
import { LoaderControls, ExampleControls, SessionControls, SnapshotControls, DatabaseControls, MesoQuickStylesControls, MesoProceduralAnimationControls, ExplorerInfo } from './states';
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
import { TuneSvg } from '../../../mol-plugin-ui/controls/icons';
import { RendererParams } from '../../../mol-gl/renderer';
import { TrackballControlsParams } from '../../../mol-canvas3d/controls/trackball';
import { XRManagerParams } from '../../../mol-canvas3d/helper/xr-manager';
const Spacer = () => <div style={{ height: '2em' }} />;
const ViewportParams = {
renderer: PD.Group(RendererParams),
trackball: PD.Group(TrackballControlsParams),
xr: PD.Group(XRManagerParams, { label: 'XR' }),
};
class ViewportSettingsUI extends CollapsableControls<{}, {}> {
@@ -143,6 +145,7 @@ export class RightPanel extends PluginUIComponent<{}, { isDisabled: boolean }> {
<StructureMeasurementsControls initiallyCollapsed={true}/>
</>
<MesoQuickStylesControls />
<MesoProceduralAnimationControls />
<Spacer />
<SectionHeader title='Entities' />
<EntityControls />

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2022-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2022-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -8,7 +8,7 @@ import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif';
import { MmcifProvider } from '../../../mol-plugin-state/formats/trajectory';
import { PluginStateObject } from '../../../mol-plugin-state/objects';
import { Button, ExpandGroup, IconButton } from '../../../mol-plugin-ui/controls/common';
import { GetAppSvg, HelpOutlineSvg, MagicWandSvg, TourSvg, Icon, OpenInBrowserSvg } from '../../../mol-plugin-ui/controls/icons';
import { AnimationSvg, GetAppSvg, HelpOutlineSvg, MagicWandSvg, TourSvg, Icon, OpenInBrowserSvg } from '../../../mol-plugin-ui/controls/icons';
import { CollapsableControls, PluginUIComponent } from '../../../mol-plugin-ui/base';
import { ApplyActionControl } from '../../../mol-plugin-ui/state/apply-action';
import { LocalStateSnapshotList, LocalStateSnapshotParams, LocalStateSnapshots } from '../../../mol-plugin-ui/state/snapshots';
@@ -24,9 +24,10 @@ import { createCellpackHierarchy } from '../data/cellpack/preset';
import { createGenericHierarchy } from '../data/generic/preset';
import { createMmcifHierarchy } from '../data/mmcif/preset';
import { createPetworldHierarchy } from '../data/petworld/preset';
import { MesoscaleState, MesoscaleStateObject, setGraphicsCanvas3DProps, updateStyle } from '../data/state';
import { getAllEntities, getAllGroups, getEntityLabel, MesoscaleState, MesoscaleStateObject, setGraphicsCanvas3DProps, updateStyle } from '../data/state';
import { isTimingMode } from '../../../mol-util/debug';
import { now } from '../../../mol-util/now';
import { readFromFile } from '../../../mol-util/data-source';
function adjustPluginProps(ctx: PluginContext) {
const customState = ctx.customState as MesoscaleExplorerState;
@@ -45,8 +46,6 @@ function adjustPluginProps(ctx: PluginContext) {
dimColor: Color(0xffffff),
dimStrength: 1,
markerPriority: 2,
interiorColorFlag: false,
interiorDarkening: 0.15,
exposure: 1.1,
xrayEdgeFalloff: 3,
},
@@ -211,27 +210,53 @@ export async function loadPdb(ctx: PluginContext, id: string) {
await createHierarchy(ctx, data.ref);
}
export async function loadPdbDev(ctx: PluginContext, id: string) {
export async function loadPdbIhm(ctx: PluginContext, id: string) {
await reset(ctx);
let url: string;
// 4 character PDB id, TODO: support extended PDB ID
if (id.match(/^[1-9][A-Z0-9]{3}$/i) !== null) {
url = `https://pdb-dev.wwpdb.org/bcif/${id.toLowerCase()}.bcif`;
url = `https://pdb-ihm.org/bcif/${id.toLowerCase()}.bcif`;
} else {
const nId = id.toUpperCase().startsWith('PDBDEV_') ? id : `PDBDEV_${id.padStart(8, '0')}`;
url = `https://pdb-dev.wwpdb.org/bcif/${nId.toUpperCase()}.bcif`;
url = `https://pdb-ihm.org/bcif/${nId.toUpperCase()}.bcif`;
}
const data = await ctx.builders.data.download({ url, isBinary: true });
await createHierarchy(ctx, data.ref);
}
async function loadColors(ctx: PluginContext, file: File) {
const colorData = await ctx.runTask(readFromFile(file, 'json'));
const update = ctx.state.data.build();
const allEntities = getAllEntities(ctx);
for (const entityCell of allEntities) {
const label = getEntityLabel(ctx, entityCell);
const tags = entityCell.transform.tags;
const fullname = (tags?.[0].replace('comp:', '') ?? '') + '.' + label;
// test each tag, siwtch to uniform color
if (fullname in colorData) {
const { x, y, z } = colorData[fullname];
const color = Color.fromRgb(x, y, z);
update.to(entityCell).update(old => {
if (old.type) {
old.colorTheme = { name: 'uniform', params: { value: color, lightness: old.colorTheme.params.lightness } };
old.type.params.color = color;
} else if (old.coloring) {
old.coloring.params.color = color;
}
});
}
}
await update.commit();
}
//
export const LoadDatabase = StateAction.build({
display: { name: 'Database', description: 'Load from Database' },
params: (a, ctx: PluginContext) => {
return {
source: PD.Select('pdb', PD.objectToOptions({ pdb: 'PDB', pdbDev: 'PDB-Dev' })),
source: PD.Select('pdb', PD.objectToOptions({ pdb: 'PDB', pdbIhm: 'PDB-IHM' })),
entry: PD.Text(''),
};
},
@@ -239,8 +264,8 @@ export const LoadDatabase = StateAction.build({
})(({ params }, ctx: PluginContext) => Task.create('Loading from database...', async taskCtx => {
if (params.source === 'pdb') {
await loadPdb(ctx, params.entry);
} else if (params.source === 'pdbDev') {
await loadPdbDev(ctx, params.entry);
} else if (params.source === 'pdbIhm') {
await loadPdbIhm(ctx, params.entry);
}
}));
@@ -299,7 +324,6 @@ export const LoadModel = StateAction.build({
}
}));
//
export class DatabaseControls extends PluginUIComponent {
componentDidMount() {
@@ -337,6 +361,30 @@ export class ExampleControls extends PluginUIComponent {
}
}
export function ColorLoaderControls({ plugin }: { plugin: PluginContext }) {
const triggerLoadColors = () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.onchange = async (e) => {
const input = e.target as HTMLInputElement;
if (!input.files || !input.files[0]) return;
const file = input.files[0];
await loadColors(plugin, new File([file], file.name));
};
input.click();
};
return (
<IconButton
svg={OpenInBrowserSvg}
title="Load Colors"
onClick={triggerLoadColors}
small
/>
);
}
export async function openState(ctx: PluginContext, file: File) {
const customState = ctx.customState as MesoscaleExplorerState;
delete customState.stateRef;
@@ -426,7 +474,7 @@ export class ExplorerInfo extends PluginUIComponent<{}, { isDisabled: boolean, s
driver.setSteps([
// Left panel
{ element: '#explorerinfo', popover: { title: 'Explorer Header Info', description: 'This section displays the explorer header with version information, documentation access, and tour navigation. Use the right and left arrow keys to navigate the tour.', side: 'left', align: 'start' } },
{ element: '#database', popover: { title: 'Import from PDB', description: 'Load structures directly from PDB and PDB-DEV databases.', side: 'bottom', align: 'start' } },
{ element: '#database', popover: { title: 'Import from PDB', description: 'Load structures directly from PDB and PDB-IHM databases.', side: 'bottom', align: 'start' } },
{ element: '#loader', popover: { title: 'Import from File', description: 'Load local files (.molx, .molj, .zip, .cif, .bcif) using this option.', side: 'bottom', align: 'start' } },
{ element: '#example', popover: { title: 'Example Models and Tours', description: 'Select from a range of example models and tours provided.', side: 'left', align: 'start' } },
{ element: '#session', popover: { title: 'Session Management', description: 'Download the current session in .molx format.', side: 'top', align: 'start' } },
@@ -486,7 +534,6 @@ export class ExplorerInfo extends PluginUIComponent<{}, { isDisabled: boolean, s
}
}
export class MesoQuickStylesControls extends CollapsableControls {
defaultState() {
return {
@@ -732,3 +779,110 @@ export class MesoQuickStyles extends PluginUIComponent {
</>;
}
}
export class MesoProceduralAnimationControls extends CollapsableControls {
defaultState() {
return {
isCollapsed: true,
header: 'Procedural Animation',
brand: { accent: 'gray' as const, svg: AnimationSvg }
};
}
renderControls() {
return <>
<MesoProceduralAnimation />
</>;
}
}
class MesoProceduralAnimation extends PluginUIComponent {
private isMembrane(cell: { transform: { tags?: string[] } }) {
return cell.transform.tags?.some(t => t.includes('mem')) ?? false;
}
async dynamics() {
const update = this.plugin.state.data.build();
const entities = getAllEntities(this.plugin);
const groups = getAllGroups(this.plugin);
for (const entity of entities) {
const membrane = this.isMembrane(entity);
update.to(entity).update(old => {
if (old.type) {
old.type.params.animation = {
...old.type.params.animation,
wiggleMode: 'position',
wiggleSpeed: 7,
wiggleAmplitude: 1,
wiggleFrequency: 0.2,
tumbleSpeed: 1,
tumbleAmplitude: membrane ? 0 : 4,
tumbleFrequency: 0.2,
};
}
});
}
for (const group of groups) {
const membrane = this.isMembrane(group);
update.to(group).update(old => {
old.animation = {
...old.animation,
wiggleMode: 'position',
wiggleSpeed: 7,
wiggleAmplitude: 1,
wiggleFrequency: 0.2,
tumbleSpeed: 1,
tumbleAmplitude: membrane ? 0 : 4,
tumbleFrequency: 0.2,
};
});
}
await update.commit();
}
async clear() {
const update = this.plugin.state.data.build();
const entities = getAllEntities(this.plugin);
const groups = getAllGroups(this.plugin);
for (const entity of entities) {
update.to(entity).update(old => {
if (old.type) {
old.type.params.animation = {
...old.type.params.animation,
wiggleAmplitude: 0,
tumbleAmplitude: 0,
};
}
});
}
for (const group of groups) {
update.to(group).update(old => {
old.animation = {
...old.animation,
wiggleAmplitude: 0,
tumbleAmplitude: 0,
};
});
}
await update.commit();
}
render() {
return <>
<div className='msp-flex-row'>
<Button noOverflow title='Enable wiggle for all entities and tumble for non-membrane entities' onClick={() => this.dynamics()} style={{ width: 'auto' }}>
Dynamics
</Button>
<Button noOverflow title='Set wiggle and tumble amplitude to zero for all entities' onClick={() => this.clear()} style={{ width: 'auto' }}>
Clear
</Button>
</div>
</>;
}
}

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { BehaviorSubject } from 'rxjs';
import { MVSData } from '../../extensions/mvs/mvs-data';
import type { MVSStoriesViewerModel } from './elements/viewer';
export type MVSStoriesCommand =
| { kind: 'load-mvs', format?: 'mvsj' | 'mvsx', url?: string, data?: MVSData | string | Uint8Array<ArrayBuffer> }
export class MVSStoriesContext {
commands = new BehaviorSubject<MVSStoriesCommand | undefined>(undefined);
state = {
viewers: new BehaviorSubject<{ name?: string, model: MVSStoriesViewerModel }[]>([]),
currentStoryData: new BehaviorSubject<string | Uint8Array<ArrayBuffer> | undefined>(undefined),
isLoading: new BehaviorSubject(false),
};
dispatch(command: MVSStoriesCommand) {
this.commands.next(command);
}
constructor(public name?: string) {
}
}
export function getMVSStoriesContext(options?: { name?: string, container?: object }): MVSStoriesContext {
const container: any = options?.container ?? window;
container.componentContexts ??= {};
const name = options?.name ?? '<default>';
if (!container.componentContexts[name]) {
container.componentContexts[name] = new MVSStoriesContext(options?.name);
}
return container.componentContexts[name];
}

View File

@@ -0,0 +1,2 @@
import './snapshot-markdown';
import './viewer';

View File

@@ -0,0 +1,152 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { BehaviorSubject, distinctUntilChanged, map } from 'rxjs';
import { PluginComponent } from '../../../mol-plugin-state/component';
import { getMVSStoriesContext, MVSStoriesContext } from '../context';
import { MVSStoriesViewerModel } from './viewer';
import { useBehavior } from '../../../mol-plugin-ui/hooks/use-behavior';
import { createRoot } from 'react-dom/client';
import { PluginStateSnapshotManager } from '../../../mol-plugin-state/manager/snapshots';
import { PluginReactContext } from '../../../mol-plugin-ui/base';
import { CSSProperties, useEffect, useState } from 'react';
import { Markdown } from '../../../mol-plugin-ui/controls/markdown';
export class MVSStoriesSnapshotMarkdownModel extends PluginComponent {
readonly context: MVSStoriesContext;
root: HTMLElement | undefined = undefined;
state = new BehaviorSubject<{
entry?: PluginStateSnapshotManager.Entry,
index?: number,
all: PluginStateSnapshotManager.Entry[],
}>({ all: [] });
get viewer() {
return this.context.state.viewers.value?.find(v => this.options?.viewerName === v.name);
}
sync() {
const mng = this.viewer?.model.plugin?.managers.snapshot;
this.state.next({
entry: mng?.current,
index: mng?.current ? mng?.getIndex(mng.current) : undefined,
all: mng?.state.entries.toArray() ?? [],
});
}
async mount(root: HTMLElement) {
this.root = root;
createRoot(root).render(<MVSStoriesSnapshotMarkdownUI model={this} />);
let currentViewer: MVSStoriesViewerModel | undefined = undefined;
let sub: { unsubscribe: () => void } | undefined = undefined;
this.subscribe(this.context.state.viewers.pipe(
map(xs => xs.find(v => this.options?.viewerName === v.name)),
distinctUntilChanged((a, b) => a?.model === b?.model)
), viewer => {
if (currentViewer !== viewer) {
currentViewer = viewer?.model;
sub?.unsubscribe();
}
if (!viewer) return;
sub = this.subscribe(viewer.model.plugin?.managers.snapshot.events.changed, () => {
this.sync();
});
this.sync();
});
this.sync();
}
constructor(private options?: { context?: { name?: string, container?: object }, viewerName?: string }) {
super();
this.context = getMVSStoriesContext(options?.context);
}
}
function Loading() {
return <div>
<div style={{ marginBottom: 16 }}><i>Loading times may vary depending on the story size, your internet connection, and device performance</i></div>
<div>Fetching data<Dots /></div>
<div>Generating animations<Dots /></div>
<div>Preparing visuals<Dots /></div>
</div>;
}
function Dots() {
const [dots, setDots] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setDots(d => (d + 1) % 4);
}, Math.random() * 500 + 300);
return () => clearInterval(interval);
}, []);
return <span>{'.'.repeat(dots)}</span>;
}
export function MVSStoriesSnapshotMarkdownUI({ model }: { model: MVSStoriesSnapshotMarkdownModel }) {
const state = useBehavior(model.state);
const isLoading = useBehavior(model.context.state.isLoading);
const style: CSSProperties = { display: 'flex', flexDirection: 'column', height: '100%' };
const className = 'mvs-stories-markdown-explanation';
if (isLoading) {
return <div style={style} className={className}>
<h3>The story will be ready momentarily</h3>
<Loading />
</div>;
}
if (state.all.length === 0) {
return <div style={style} className={className}>
<i>No snapshot loaded or no description available</i>
</div>;
}
return <div style={style} className={className}>
<div style={{ display: 'flex', flexDirection: 'row', width: '100%', gap: '8px' }}>
<span style={{ lineHeight: '38px', minWidth: 60, maxWidth: 60, flexShrink: 0 }}>{typeof state.index === 'number' ? state.index + 1 : '-'}/{state.all.length}</span>
<button onClick={() => model.viewer?.model.plugin?.managers.snapshot.applyNext(-1)} style={{ flexGrow: 1, flexShrink: 0 }}>Prev</button>
<button onClick={() => model.viewer?.model.plugin?.managers.snapshot.applyNext(1)} style={{ flexGrow: 1, flexShrink: 0 }}>Next</button>
</div>
<div style={{ flexGrow: 1, overflow: 'hidden', overflowY: 'auto', position: 'relative' }}>
<div style={{ position: 'absolute', inset: 0 }}>
<PluginReactContext.Provider value={model.viewer?.model.plugin as any}>
<Markdown>{state.entry?.description ?? 'Description not available'}</Markdown>
</PluginReactContext.Provider>
</div>
</div>
</div>;
}
export class MVSStoriesSnapshotMarkdownViewer extends HTMLElement {
private model: MVSStoriesSnapshotMarkdownModel | undefined = undefined;
async connectedCallback() {
this.model = new MVSStoriesSnapshotMarkdownModel({
context: { name: this.getAttribute('context-name') ?? undefined },
viewerName: this.getAttribute('viewer-name') ?? undefined,
});
await this.model.mount(this);
}
disconnectedCallback() {
this.model?.dispose();
this.model = undefined;
}
constructor() {
super();
}
}
window.customElements.define('mvs-stories-snapshot-markdown', MVSStoriesSnapshotMarkdownViewer);

View File

@@ -0,0 +1,131 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { MolViewSpec } from '../../../extensions/mvs/behavior';
import { loadMVSData } from '../../../extensions/mvs/components/formats';
import { MVSData } from '../../../extensions/mvs/mvs-data';
import { StringLike } from '../../../mol-io/common/string-like';
import { PluginComponent } from '../../../mol-plugin-state/component';
import { createPluginUI } from '../../../mol-plugin-ui';
import { renderReact18 } from '../../../mol-plugin-ui/react18';
import { DefaultPluginUISpec } from '../../../mol-plugin-ui/spec';
import { PluginCommands } from '../../../mol-plugin/commands';
import { PluginConfig } from '../../../mol-plugin/config';
import { PluginContext } from '../../../mol-plugin/context';
import { PluginSpec } from '../../../mol-plugin/spec';
import { getMVSStoriesContext, MVSStoriesContext } from '../context';
export class MVSStoriesViewerModel extends PluginComponent {
readonly context: MVSStoriesContext;
plugin?: PluginContext = undefined;
async mount(root: HTMLElement) {
const spec = DefaultPluginUISpec();
this.plugin = await createPluginUI({
target: root,
render: renderReact18,
spec: {
...spec,
layout: {
initial: {
isExpanded: false,
showControls: false,
controlsDisplay: 'landscape',
},
},
components: {
remoteState: 'none',
viewport: {
snapshotDescription: EmptyDescription,
}
},
behaviors: [
...spec.behaviors,
PluginSpec.Behavior(MolViewSpec)
],
config: [
[PluginConfig.Viewport.ShowAnimation, false],
]
}
});
this.subscribe(this.context.commands, async (cmd) => {
if (!cmd || !this.plugin) return;
try {
this.context.state.isLoading.next(true);
if (cmd.kind === 'load-mvs') {
let loadedData: MVSData | StringLike | Uint8Array | undefined;
if (cmd.url) {
const data = await this.plugin.runTask(this.plugin.fetch({ url: cmd.url, type: cmd.format === 'mvsx' ? 'binary' : 'string' }));
loadedData = await loadMVSData(this.plugin, data, cmd.format ?? 'mvsj', { sourceUrl: cmd.url });
} else if (cmd.data) {
loadedData = await loadMVSData(this.plugin, cmd.data, cmd.format ?? 'mvsj');
}
if (StringLike.is(loadedData) || loadedData instanceof Uint8Array) {
this.context.state.currentStoryData.next(loadedData as string | Uint8Array<ArrayBuffer>);
} else if (loadedData) {
this.context.state.currentStoryData.next(JSON.stringify(loadedData));
}
}
} catch (e) {
console.error(e);
PluginCommands.Toast.Show(
this.plugin,
{ key: '<mvsload>', title: 'Error', message: e?.message ? `${e?.message}` : `${e}`, timeoutMs: 10000 }
);
} finally {
this.context.state.isLoading.next(false);
}
});
const viewers = this.context.state.viewers.value;
const next = [...viewers, { name: this.options?.name, model: this }];
this.context.state.viewers.next(next);
}
constructor(private options?: { context?: { name?: string, container?: object }, name?: string }) {
super();
this.context = getMVSStoriesContext(options?.context);
const viewers = this.context.state.viewers.value;
const index = viewers.findIndex(v => v.name === options?.name);
if (index >= 0) {
const next = [...viewers];
next[index].model.dispose();
next.splice(index, 0);
this.context.state.viewers.next(next);
}
}
}
function EmptyDescription() {
return <></>;
}
export class MVSStoriesViewer extends HTMLElement {
private model: MVSStoriesViewerModel | undefined = undefined;
async connectedCallback() {
this.model = new MVSStoriesViewerModel({
name: this.getAttribute('name') ?? undefined,
context: { name: this.getAttribute('context-name') ?? undefined },
});
await this.model.mount(this);
}
disconnectedCallback() {
this.model?.dispose();
this.model = undefined;
}
constructor() {
super();
}
}
window.customElements.define('mvs-stories-viewer', MVSStoriesViewer);

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,148 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="icon" href="./favicon.ico" type="image/x-icon">
<title>Molecular Stories</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#viewer {
position: absolute;
left: 0;
top: 0;
right: 34%;
bottom: 0;
}
#controls {
position: absolute;
left: 66%;
top: 0;
right: 0;
bottom: 0;
padding: 16px;
padding-bottom: 20px;
border: 1px solid #ccc;
border-left: none;
background: #F6F5F3;
z-index: -2;
display: flex;
flex-direction: column;
gap: 16px;
}
#links {
position: absolute;
bottom: 4px;
right: 8px;
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 0.6rem;
z-index: -1;
color: #666;
}
#links a {
color: #666;
text-decoration: none;
}
#links .sep {
color: #aaa;
}
@media (orientation:portrait) {
#viewer {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 40%;
}
#controls {
position: absolute;
left: 0;
top: 60%;
right: 0;
bottom: 0;
border-top: none;
}
.msp-viewport-controls-buttons {
display: none;
}
}
</style>
<link rel="stylesheet" type="text/css" href="mvs-stories.css" />
<script type="text/javascript" src="mvs-stories.js"></script>
</head>
<body>
<!-- the context-name parameter is optional and useful when embedding multiple stories in a single page -->
<div id="viewer">
<mvs-stories-viewer context-name="story1" ></mvs-stories-viewer>
</div>
<div id="controls">
<mvs-stories-snapshot-markdown context-name="story1" style="flex-grow: 1;" ></mvs-stories-snapshot-markdown>
</div>
<div id="links">
<span id="open-in-stories" style="display: none;"><a href="#" id="open-in-stories-link" target="_blank" rel="noopener noreferrer" title="Open and edit the story in the MolViewStories app">Edit in MolViewStories</a>&nbsp;<span class="sep"></span></span>
<span id="open-in-molstar" style="display: none;"><a href="#" id="open-in-molstar-link" target="_blank" rel="noopener noreferrer" title="Open the story in the Mol* Viewer app. Enables exporting an animation.">Open in Mol* Viewer</a>&nbsp;<span class="sep"></span></span>
<a href="#" id="mvs-data" title="MolViewSpec State for this story. Can be opened in the Mol* app.">Download MVS</a> <span class="sep"></span> <a href="https://github.com/molstar/molstar/tree/master/src/apps/mvs-stories" id="mvs-data" target="_blank" rel="noopener noreferrer">Source Code</a>
</div>
<script>
var urlParams = new URLSearchParams(window.location.search);
var storyId = urlParams.get('story-id');
var storyUrl = urlParams.get('story-url');
var storySessionUrl = urlParams.get('story-session-url');
var format = urlParams.get('data-format');
// For testing purposes:
// if (!storyUrl) {
// storyUrl = 'https://raw.githubusercontent.com/molstar/molstar/master/examples/mvs/kinase-story.mvsj';
// }
var molstarDataLink = storyUrl;
var editInStoriesUrl = undefined;
if (storyId) {
mvsStories.loadFromID(storyId, { format: format || 'mvsj', contextName: 'story1' });
editInStoriesUrl = 'https://molstar.org/mol-view-stories/builder?published-session-id=' + storyId;
molstarDataLink = 'https://stories.molstar.org/api/story/' + storyId + '/data';
} else if (storyUrl) {
mvsStories.loadFromURL(storyUrl, { format: format || 'mvsj', contextName: 'story1' });
}
if (!editInStoriesUrl && storySessionUrl) {
editInStoriesUrl = 'https://molstar.org/mol-view-stories/builder?session-url=' + encodeURIComponent(storySessionUrl);
}
if (molstarDataLink) {
var molstarLink = 'https://molstar.org/viewer?mvs-url=' + encodeURIComponent(molstarDataLink) + '&mvs-format=' + encodeURIComponent(format || 'mvsj');
document.getElementById('open-in-molstar-link').setAttribute('href', molstarLink);
document.getElementById('open-in-molstar').style.display = 'inline';
}
if (editInStoriesUrl) {
document.getElementById('open-in-stories-link').setAttribute('href', editInStoriesUrl);
document.getElementById('open-in-stories').style.display = 'inline';
}
document.getElementById('mvs-data').addEventListener('click', (e) => {
e.preventDefault();
mvsStories.downloadCurrentStory({ contextName: 'story1' });
});
</script>
<!-- __MOLSTAR_ANALYTICS__ -->
</body>
</html>

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { getMVSStoriesContext } from './context';
import './elements';
import { MVSData } from '../../extensions/mvs/mvs-data';
import { download } from '../../mol-util/download';
import './favicon.ico';
import '../../mol-plugin-ui/skin/light.scss';
import './styles.scss';
import './index.html';
export function getContext(name?: string) {
return getMVSStoriesContext({ name });
}
export function loadFromURL(url: string, options?: { format: 'mvsx' | 'mvsj', contextName?: string }) {
setTimeout(() => {
getContext(options?.contextName).dispatch({
kind: 'load-mvs',
format: options?.format ?? 'mvsj',
url,
});
}, 0);
}
export function loadFromData(data: MVSData | string | Uint8Array<ArrayBuffer>, options?: { format: 'mvsx' | 'mvsj', contextName?: string }) {
setTimeout(() => {
getContext(options?.contextName).dispatch({
kind: 'load-mvs',
format: options?.format ?? 'mvsj',
data,
});
}, 0);
}
function getStoryUrlFromId(id: string, format: 'mvsx' | 'mvsj' = 'mvsj') {
return `https://stories.molstar.org/api/story/${id}/data`;
}
export function loadFromID(id: string, options?: { format?: 'mvsx' | 'mvsj', contextName?: string }) {
loadFromURL(
getStoryUrlFromId(id, options?.format),
{ format: options?.format ?? 'mvsj', contextName: options?.contextName },
);
}
export function downloadCurrentStory(options?: { contextName?: string, filename?: string }) {
const story = getContext(options?.contextName).state.currentStoryData.value;
if (!story) return;
const isMVSJ = typeof story === 'string';
const filename = `${options?.filename ?? 'story'}.${isMVSJ ? 'mvsj' : 'mvsx'}`;
download(
new Blob([typeof story === 'string' ? story : story.buffer], { type: isMVSJ ? 'application/json' : 'application/octet-stream' }),
filename
);
};
export { MVSData };

View File

@@ -0,0 +1,66 @@
# MolViewSpec Stories App
An app that defines `mvs-stories-snapshot-markdown` and `mvs-stories-viewer` web components that can be used to view MolViewSpec molecular stories.
See the [mvs-stories](../../examples/mvs-stories) example that includes specific stories.
### Usage
- Get `mvs-stories.css` and `mvs-stories.js` from `build/mvs-stories` and include these to your HTML page
```html
<link rel="stylesheet" type="text/css" href="mvs-stories.css" />
<script type="text/javascript" src="mvs-stories.js"></script>
```
Can also use `https://cdn.jsdelivr.net/npm/molstar@latest/build/mvs-stories/mvs-stories.js` (and `.css`). `latest` can be substituted by specific version.
- Place the components in your page wrapper in `<div>` elements to set up positioning:
```html
<div class="viewer">
<mvs-stories-viewer />
</div>
<div class="snapshot">
<mvs-stories-snapshot-markdown />
</div>
```
- Load MolViewSpec state:
```html
<script>
mvsStories.loadFromURL('https://raw.githubusercontent.com/molstar/molstar/master/examples/mvs/1cbs.mvsj');
</script>
```
- See [index.html](./index.html) for full example of how to embed the app.
- For interactive development build (for production use `npm run build`) of the example that immediately reflects changes use:
```bash
npm run dev -- -a mvs-stories
```
### Multiple Stories on a Single Page
To support multiple instances of stories, use the `context-name='unique-name'` attribute on the `mvs-` components together with `loadFromURL/Data(..., { contextName: 'unique-name' })`.
For example (simplified to not include layout):
```html
<div>
<mvs-stories-viewer context-name="1" />
<mvs-stories-snapshot-markdown context-name="1" />
</div>
<div>
<mvs-stories-viewer context-name="2" />
<mvs-stories-snapshot-markdown context-name="2" />
</div>
<script>
mvsStories.loadFromURL('1.mvsj', { format: 'mvsj', contextName: '1' });
mvsStories.loadFromURL('2.mvsj', { format: 'mvsj', contextName: '2' });
</script>
```

View File

@@ -0,0 +1,204 @@
@use '../../mol-plugin-ui/skin/base/components/markdown.scss';
.mvs-stories-markdown-explanation {
// Adapted from skeleton.css, The MIT License (MIT), Copyright (c) 2011-2014 Dave Gamache
line-height: 1.4;
font-weight: 400;
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #222;
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 0;
margin-bottom: 1rem;
font-weight: 300;
}
h1 {
font-size: 3rem;
line-height: 1.2;
letter-spacing: -.1rem;
}
h2 {
font-size: 2.6rem;
line-height: 1.25;
letter-spacing: -.1rem;
}
h3 {
font-size: 2rem;
line-height: 1.3;
letter-spacing: -.1rem;
}
h4 {
font-size: 1.7rem;
line-height: 1.35;
letter-spacing: -.08rem;
}
h5 {
font-size: 1.4rem;
line-height: 1.5;
letter-spacing: -.05rem;
}
h6 {
font-size: 1.1rem;
line-height: 1.6;
letter-spacing: 0;
}
button {
display: inline-block;
height: 38px;
padding: 0 24px;
color: #555;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border-radius: 4px;
border: 1px solid #bbb;
cursor: pointer;
box-sizing: border-box;
}
ul {
list-style: circle inside;
}
ol {
list-style: decimal inside;
}
ol,
ul {
padding-left: 0;
margin-top: 0;
}
ul ul,
ul ol,
ol ol,
ol ul {
margin: 1.5rem 0 1.5rem 3rem;
font-size: 90%;
}
li {
margin-bottom: 0.2rem;
}
code {
padding: .2rem .5rem;
margin: 0 .2rem;
font-size: 90%;
white-space: nowrap;
background: #F1F1F1;
border: 1px solid #E1E1E1;
border-radius: 4px;
}
pre>code {
display: block;
padding: 1rem 1.5rem;
white-space: pre;
}
th,
td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #E1E1E1;
}
th:first-child,
td:first-child {
padding-left: 0;
}
th:last-child,
td:last-child {
padding-right: 0;
}
button,
.button {
margin-bottom: 1rem;
}
input,
textarea,
select,
fieldset {
margin-bottom: 1.5rem;
}
pre,
blockquote,
dl,
figure,
table,
p,
ul,
ol,
form {
margin-bottom: 1rem;
}
hr {
margin-top: 1rem;
margin-bottom: 1rem;
border-width: 0;
border-top: 1px solid #E1E1E1;
}
table {
border: 1px solid #E1E1E1;
border-collapse: collapse;
}
th {
text-align: left;
}
th, td {
border: 1px solid #E1E1E1;
padding: 4px 8px;
}
img {
max-width: 100%;
height: auto;
}
a {
text-decoration: none;
color: #1d4ed7;
&:hover {
text-decoration: underline;
}
}
}
@media (orientation:portrait) {
.mvs-stories-markdown-explanation {
font-size: 0.9rem;
}
.mvs-stories-markdown-explanation h3 {
font-size: 1.5rem;
}
}

View File

@@ -0,0 +1,7 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
export const VERSION = 1;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 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>
@@ -7,35 +7,20 @@
* @author Adam Midlik <midlik@gmail.com>
*/
import { ANVILMembraneOrientation } from '../../extensions/anvil/behavior';
import { Backgrounds } from '../../extensions/backgrounds';
import { DnatcoNtCs } from '../../extensions/dnatco';
import { G3DFormat, G3dProvider } from '../../extensions/g3d/format';
import { GeometryExport } from '../../extensions/geo-export';
import { MAQualityAssessment, MAQualityAssessmentConfig, QualityAssessmentPLDDTPreset, QualityAssessmentQmeanPreset } from '../../extensions/model-archive/quality-assessment/behavior';
import { QualityAssessment } from '../../extensions/model-archive/quality-assessment/prop';
import { ModelExport } from '../../extensions/model-export';
import { Mp4Export } from '../../extensions/mp4-export';
import { MolViewSpec } from '../../extensions/mvs/behavior';
import { loadMVSX } from '../../extensions/mvs/components/formats';
import { AssemblySymmetryConfig } from '../../extensions/assembly-symmetry';
import { loadMVSData, loadMVSX } from '../../extensions/mvs/components/formats';
import { loadMVS, MolstarLoadingExtension } from '../../extensions/mvs/load';
import { MVSData } from '../../extensions/mvs/mvs-data';
import { PDBeStructureQualityReport } from '../../extensions/pdbe';
import { RCSBValidationReport } from '../../extensions/rcsb';
import { AssemblySymmetry, AssemblySymmetryConfig } from '../../extensions/assembly-symmetry';
import { SbNcbrPartialCharges, SbNcbrPartialChargesPreset, SbNcbrPartialChargesPropertyProvider, SbNcbrTunnels } from '../../extensions/sb-ncbr';
import { Volseg, VolsegVolumeServerConfig } from '../../extensions/volumes-and-segmentations';
import { wwPDBChemicalComponentDictionary } from '../../extensions/wwpdb/ccd/behavior';
import { wwPDBStructConnExtensionFunctions } from '../../extensions/wwpdb/struct-conn';
import { ZenodoImport } from '../../extensions/zenodo';
import { SaccharideCompIdMapType } from '../../mol-model/structure/structure/carbohydrates/constants';
import { StringLike } from '../../mol-io/common/string-like';
import { Structure, StructureElement } from '../../mol-model/structure';
import { Volume } from '../../mol-model/volume';
import { OpenFiles } from '../../mol-plugin-state/actions/file';
import { DownloadStructure, PdbDownloadProvider } from '../../mol-plugin-state/actions/structure';
import { DownloadDensity } from '../../mol-plugin-state/actions/volume';
import { PresetTrajectoryHierarchy } from '../../mol-plugin-state/builder/structure/hierarchy-preset';
import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
import { StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
import { PluginComponent } from '../../mol-plugin-state/component';
import { BuiltInCoordinatesFormat } from '../../mol-plugin-state/formats/coordinates';
import { DataFormatProvider } from '../../mol-plugin-state/formats/provider';
import { BuiltInTopologyFormat } from '../../mol-plugin-state/formats/topology';
import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
import { BuildInVolumeFormat } from '../../mol-plugin-state/formats/volume';
@@ -43,95 +28,39 @@ import { createVolumeRepresentationParams } from '../../mol-plugin-state/helpers
import { PluginStateObject } from '../../mol-plugin-state/objects';
import { StateTransforms } from '../../mol-plugin-state/transforms';
import { TrajectoryFromModelAndCoordinates } from '../../mol-plugin-state/transforms/model';
import { PluginUIContext } from '../../mol-plugin-ui/context';
import { createPluginUI } from '../../mol-plugin-ui';
import { PluginUIContext } from '../../mol-plugin-ui/context';
import { renderReact18 } from '../../mol-plugin-ui/react18';
import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
import { PluginBehaviors } from '../../mol-plugin/behavior';
import { PluginCommands } from '../../mol-plugin/commands';
import { PluginConfig, PluginConfigItem } from '../../mol-plugin/config';
import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
import { PluginSpec } from '../../mol-plugin/spec';
import { PluginConfig } from '../../mol-plugin/config';
import { PluginState } from '../../mol-plugin/state';
import { StateObjectRef, StateObjectSelector } from '../../mol-state';
import { MolScriptBuilder } from '../../mol-script/language/builder';
import { Expression } from '../../mol-script/language/expression';
import { StateObjectSelector } from '../../mol-state';
import { Task } from '../../mol-task';
import { Asset } from '../../mol-util/assets';
import { Color } from '../../mol-util/color';
import '../../mol-util/polyfill';
import { ObjectKeys } from '../../mol-util/type-helpers';
import { ExtensionMap } from './extensions';
import { DefaultViewerOptions, ViewerOptions } from './options';
export { PLUGIN_VERSION as version } from '../../mol-plugin/version';
export { consoleStats, setDebugMode, setProductionMode, setTimingMode } from '../../mol-util/debug';
export { consoleStats, isDebugMode, isProductionMode, isTimingMode, setDebugMode, setProductionMode, setTimingMode } from '../../mol-util/debug';
const CustomFormats = [
['g3d', G3dProvider] as const
];
export const ExtensionMap = {
'volseg': PluginSpec.Behavior(Volseg),
'backgrounds': PluginSpec.Behavior(Backgrounds),
'dnatco-ntcs': PluginSpec.Behavior(DnatcoNtCs),
'pdbe-structure-quality-report': PluginSpec.Behavior(PDBeStructureQualityReport),
'assembly-symmetry': PluginSpec.Behavior(AssemblySymmetry),
'rcsb-validation-report': PluginSpec.Behavior(RCSBValidationReport),
'anvil-membrane-orientation': PluginSpec.Behavior(ANVILMembraneOrientation),
'g3d': PluginSpec.Behavior(G3DFormat),
'model-export': PluginSpec.Behavior(ModelExport),
'mp4-export': PluginSpec.Behavior(Mp4Export),
'geo-export': PluginSpec.Behavior(GeometryExport),
'ma-quality-assessment': PluginSpec.Behavior(MAQualityAssessment),
'zenodo-import': PluginSpec.Behavior(ZenodoImport),
'sb-ncbr-partial-charges': PluginSpec.Behavior(SbNcbrPartialCharges),
'wwpdb-chemical-component-dictionary': PluginSpec.Behavior(wwPDBChemicalComponentDictionary),
'mvs': PluginSpec.Behavior(MolViewSpec),
'tunnels': PluginSpec.Behavior(SbNcbrTunnels),
};
const DefaultViewerOptions = {
customFormats: CustomFormats as [string, DataFormatProvider][],
extensions: ObjectKeys(ExtensionMap),
disabledExtensions: [] as string[],
layoutIsExpanded: true,
layoutShowControls: true,
layoutShowRemoteState: true,
layoutControlsDisplay: 'reactive' as PluginLayoutControlsDisplay,
layoutShowSequence: true,
layoutShowLog: true,
layoutShowLeftPanel: true,
collapseLeftPanel: false,
collapseRightPanel: false,
disableAntialiasing: PluginConfig.General.DisableAntialiasing.defaultValue,
pixelScale: PluginConfig.General.PixelScale.defaultValue,
pickScale: PluginConfig.General.PickScale.defaultValue,
transparency: PluginConfig.General.Transparency.defaultValue,
preferWebgl1: PluginConfig.General.PreferWebGl1.defaultValue,
allowMajorPerformanceCaveat: PluginConfig.General.AllowMajorPerformanceCaveat.defaultValue,
powerPreference: PluginConfig.General.PowerPreference.defaultValue,
resolutionMode: PluginConfig.General.ResolutionMode.defaultValue,
illumination: false,
viewportShowExpand: PluginConfig.Viewport.ShowExpand.defaultValue,
viewportShowControls: PluginConfig.Viewport.ShowControls.defaultValue,
viewportShowSettings: PluginConfig.Viewport.ShowSettings.defaultValue,
viewportShowSelectionMode: PluginConfig.Viewport.ShowSelectionMode.defaultValue,
viewportShowAnimation: PluginConfig.Viewport.ShowAnimation.defaultValue,
viewportShowTrajectoryControls: PluginConfig.Viewport.ShowTrajectoryControls.defaultValue,
pluginStateServer: PluginConfig.State.DefaultServer.defaultValue,
volumeStreamingServer: PluginConfig.VolumeStreaming.DefaultServer.defaultValue,
volumeStreamingDisabled: !PluginConfig.VolumeStreaming.Enabled.defaultValue,
pdbProvider: PluginConfig.Download.DefaultPdbProvider.defaultValue,
emdbProvider: PluginConfig.Download.DefaultEmdbProvider.defaultValue,
saccharideCompIdMapType: 'default' as SaccharideCompIdMapType,
volumesAndSegmentationsDefaultServer: VolsegVolumeServerConfig.DefaultServer.defaultValue,
rcsbAssemblySymmetryDefaultServerType: AssemblySymmetryConfig.DefaultServerType.defaultValue,
rcsbAssemblySymmetryDefaultServerUrl: AssemblySymmetryConfig.DefaultServerUrl.defaultValue,
rcsbAssemblySymmetryApplyColors: AssemblySymmetryConfig.ApplyColors.defaultValue,
config: [] as [PluginConfigItem, any][],
};
type ViewerOptions = typeof DefaultViewerOptions;
import { decodeColor } from '../../mol-util/color/utils';
import '../../mol-util/polyfill';
import { ViewerAutoPreset } from './presets';
import { CameraFocusLociOptions } from '../../mol-plugin-state/manager/camera';
import { PluginSpec } from '../../mol-plugin/spec';
import { NoPrimaryFocusLociBindings } from '../../mol-plugin/behavior/dynamic/camera';
export class Viewer {
constructor(public plugin: PluginUIContext) {
private _events = new PluginComponent();
public readonly plugin: PluginUIContext;
constructor(plugin: PluginUIContext) {
this.plugin = plugin;
}
static async create(elementOrId: string | HTMLElement, options: Partial<ViewerOptions> = {}) {
@@ -146,11 +75,31 @@ export class Viewer {
const defaultSpec = DefaultPluginUISpec();
const disabledExtension = new Set(o.disabledExtensions ?? []);
let baseBehaviors = defaultSpec.behaviors;
if (o.viewportFocusBehavior === 'disabled') {
baseBehaviors = baseBehaviors.filter(b =>
b.transformer !== PluginBehaviors.Camera.FocusLoci
&& b.transformer !== PluginBehaviors.Representation.FocusLoci
);
} else if (o.viewportFocusBehavior === 'secondary-zoom') {
baseBehaviors = baseBehaviors.filter(b =>
b.transformer !== PluginBehaviors.Camera.FocusLoci
&& b.transformer !== PluginBehaviors.Representation.FocusLoci
);
baseBehaviors.push(PluginSpec.Behavior(PluginBehaviors.Camera.FocusLoci, {
bindings: NoPrimaryFocusLociBindings
}));
}
const spec: PluginUISpec = {
canvas3d: {
...defaultSpec.canvas3d,
},
actions: defaultSpec.actions,
behaviors: [
...defaultSpec.behaviors,
...baseBehaviors,
...o.extensions.filter(e => !disabledExtension.has(e)).map(e => ExtensionMap[e]),
],
animations: [...defaultSpec.animations || []],
@@ -188,8 +137,11 @@ export class Viewer {
[PluginConfig.General.AllowMajorPerformanceCaveat, o.allowMajorPerformanceCaveat],
[PluginConfig.General.PowerPreference, o.powerPreference],
[PluginConfig.General.ResolutionMode, o.resolutionMode],
[PluginConfig.Viewport.ShowExpand, o.viewportShowExpand],
[PluginConfig.Viewport.ShowReset, o.viewportShowReset],
[PluginConfig.Viewport.ShowScreenshotControls, o.viewportShowScreenshotControls],
[PluginConfig.Viewport.ShowControls, o.viewportShowControls],
[PluginConfig.Viewport.ShowExpand, o.viewportShowExpand],
[PluginConfig.Viewport.ShowToggleFullscreen, o.viewportShowToggleFullscreen],
[PluginConfig.Viewport.ShowSettings, o.viewportShowSettings],
[PluginConfig.Viewport.ShowSelectionMode, o.viewportShowSelectionMode],
[PluginConfig.Viewport.ShowAnimation, o.viewportShowAnimation],
@@ -202,7 +154,6 @@ export class Viewer {
[PluginConfig.Download.DefaultEmdbProvider, o.emdbProvider],
[PluginConfig.Structure.DefaultRepresentationPreset, ViewerAutoPreset.id],
[PluginConfig.Structure.SaccharideCompIdMapType, o.saccharideCompIdMapType],
[VolsegVolumeServerConfig.DefaultServer, o.volumesAndSegmentationsDefaultServer],
[AssemblySymmetryConfig.DefaultServerType, o.rcsbAssemblySymmetryDefaultServerType],
[AssemblySymmetryConfig.DefaultServerUrl, o.rcsbAssemblySymmetryDefaultServerUrl],
[AssemblySymmetryConfig.ApplyColors, o.rcsbAssemblySymmetryApplyColors],
@@ -224,10 +175,23 @@ export class Viewer {
plugin.builders.structure.representation.registerPreset(ViewerAutoPreset);
}
});
plugin.canvas3d?.setProps({ illumination: { enabled: o.illumination } });
if (o.viewportBackgroundColor) {
const backgroundColor = decodeColor(o.viewportBackgroundColor);
if (typeof backgroundColor === 'number') {
plugin.canvas3d?.setProps({ renderer: { backgroundColor } });
}
}
return new Viewer(plugin);
}
/**
* Allows subscribing to rxjs observables in the context of the viewer.
* All subscriptions will be disposed of when the viewer is destroyed.
*/
subscribe = this._events.subscribe.bind(this._events);
setRemoteSnapshot(id: string) {
const url = `${this.plugin.config.get(PluginConfig.State.CurrentServer)}/get/${id}`;
return PluginCommands.State.Snapshots.Fetch(this.plugin, { url });
@@ -288,14 +252,21 @@ export class Viewer {
}));
}
/**
* @deprecated Scheduled for removal in v5. Use {@link loadPdbIhm | loadPdbIhm(pdbIhm: string)} instead.
*/
loadPdbDev(pdbDev: string) {
return this.loadPdbIhm(pdbDev);
}
loadPdbIhm(pdbIhm: string) {
const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
source: {
name: 'pdb-dev' as const,
name: 'pdb-ihm' as const,
params: {
provider: {
id: pdbDev,
id: pdbIhm,
encoding: 'bcif',
},
options: params.source.params.options,
@@ -489,7 +460,8 @@ export class Viewer {
: await plugin.builders.data.download({ url: params.model.url, isBinary: params.model.isBinary, label: params.modelLabel });
const provider = plugin.dataFormats.get(params.model.format);
model = await provider!.parse(plugin, data);
const parsed = await provider!.parse(plugin, data);
model = parsed.topology;
}
const data = params.coordinates.kind === 'coordinates-data'
@@ -511,15 +483,15 @@ export class Viewer {
return { model, coords, preset };
}
async loadMvsFromUrl(url: string, format: 'mvsj' | 'mvsx', options?: { replaceExisting?: boolean, keepCamera?: boolean, extensions?: MolstarLoadingExtension<any>[] }) {
async loadMvsFromUrl(url: string, format: 'mvsj' | 'mvsx', options?: { appendSnapshots?: boolean, keepCamera?: boolean, keepCameraOrientation?: boolean, extensions?: MolstarLoadingExtension<any>[] }) {
if (format === 'mvsj') {
const data = await this.plugin.runTask(this.plugin.fetch({ url, type: 'string' }));
const mvsData = MVSData.fromMVSJ(data);
const mvsData = MVSData.fromMVSJ(StringLike.toString(data));
await loadMVS(this.plugin, mvsData, { sanityChecks: true, sourceUrl: url, ...options });
} else if (format === 'mvsx') {
const data = await this.plugin.runTask(this.plugin.fetch({ url, type: 'binary' }));
await this.plugin.runTask(Task.create('Load MVSX file', async ctx => {
const parsed = await loadMVSX(this.plugin, ctx, data);
const parsed = await loadMVSX(this.plugin, ctx, data, { doNotClearAssets: options?.appendSnapshots });
await loadMVS(this.plugin, parsed.mvsData, { sanityChecks: true, sourceUrl: parsed.sourceUrl, ...options });
}));
} else {
@@ -530,26 +502,24 @@ export class Viewer {
/** Load MolViewSpec from `data`.
* If `format` is 'mvsj', `data` must be a string or a Uint8Array containing a UTF8-encoded string.
* If `format` is 'mvsx', `data` must be a Uint8Array or a string containing base64-encoded binary data prefixed with 'base64,'. */
async loadMvsData(data: string | Uint8Array, format: 'mvsj' | 'mvsx', options?: { replaceExisting?: boolean, keepCamera?: boolean, extensions?: MolstarLoadingExtension<any>[] }) {
if (typeof data === 'string' && data.startsWith('base64')) {
data = Uint8Array.from(atob(data.substring(7)), c => c.charCodeAt(0)); // Decode base64 string to Uint8Array
}
if (format === 'mvsj') {
if (typeof data !== 'string') {
data = new TextDecoder().decode(data); // Decode Uint8Array to string using UTF8
}
const mvsData = MVSData.fromMVSJ(data);
await loadMVS(this.plugin, mvsData, { sanityChecks: true, sourceUrl: undefined, ...options });
} else if (format === 'mvsx') {
if (typeof data === 'string') {
throw new Error("loadMvsData: if `format` is 'mvsx', then `data` must be a Uint8Array or a base64-encoded string prefixed with 'base64,'.");
}
await this.plugin.runTask(Task.create('Load MVSX file', async ctx => {
const parsed = await loadMVSX(this.plugin, ctx, data as Uint8Array);
await loadMVS(this.plugin, parsed.mvsData, { sanityChecks: true, sourceUrl: parsed.sourceUrl, ...options });
}));
loadMvsData(data: string | Uint8Array<ArrayBuffer>, format: 'mvsj' | 'mvsx', options?: { appendSnapshots?: boolean, keepCamera?: boolean, keepCameraOrientation?: boolean, extensions?: MolstarLoadingExtension<any>[] }) {
return loadMVSData(this.plugin, data, format, options);
}
loadFiles(files: File[]) {
const sessions = files.filter(f => {
const fn = f.name.toLowerCase();
return fn.endsWith('.molx') || fn.endsWith('.molj');
});
if (sessions.length > 0) {
return PluginCommands.State.Snapshots.OpenFile(this.plugin, { file: sessions[0] });
} else {
throw new Error(`Unknown MolViewSpec format: ${format}`);
return this.plugin.runTask(this.plugin.state.data.applyAction(OpenFiles, {
files: files.map(f => Asset.File(f)),
format: { name: 'auto', params: {} },
visuals: true
}));
}
}
@@ -557,7 +527,66 @@ export class Viewer {
this.plugin.layout.events.updated.next(void 0);
}
/**
* Triggers structure element selection or highlighting based on the provided
* MolScript expression or StructureElement schema. Focus action will only apply to the
* first structure that matches the criteria.
*
* If neither `expression` nor `elements` are provided, all selections/highlights
* will be cleared based on the specified `action`.
*/
structureInteractivity({ expression, elements, action: action_, applyGranularity = false, filterStructure, focusOptions }: {
expression?: (queryBuilder: typeof MolScriptBuilder) => Expression,
elements?: StructureElement.Schema,
action: 'highlight' | 'select' | 'focus' | ('highlight' | 'select' | 'focus')[],
applyGranularity?: boolean,
filterStructure?: (structure: Structure) => boolean,
focusOptions?: Partial<CameraFocusLociOptions>
}) {
const plugin = this.plugin;
const actions = Array.isArray(action_) ? action_ : [action_];
if (!expression && !elements) {
if (actions.includes('select')) {
plugin.managers.interactivity.lociSelects.deselectAll();
}
if (actions.includes('highlight')) {
plugin.managers.interactivity.lociHighlights.clearHighlights();
}
return;
}
if (actions.includes('select')) {
plugin.managers.interactivity.lociSelects.deselectAll();
}
const structures = this.plugin.state.data.selectQ(Q => Q.rootsOfType(PluginStateObject.Molecule.Structure));
let focused = false;
for (const s of structures) {
if (!s.obj?.data) continue;
if (filterStructure && !filterStructure(s.obj.data)) continue;
const loci = expression
? StructureElement.Loci.fromExpression(s.obj.data, expression)
: StructureElement.Loci.fromSchema(s.obj.data, elements!);
for (const action of actions) {
if (action === 'select') {
plugin.managers.interactivity.lociSelects.select({ loci }, applyGranularity);
} else if (action === 'highlight') {
plugin.managers.interactivity.lociHighlights.highlight({ loci }, applyGranularity);
} else if (action === 'focus' && !StructureElement.Loci.isEmpty(loci) && !focused) {
plugin.managers.camera.focusLoci(loci, focusOptions);
focused = true;
if (actions.length === 1) return; // if only focusing, focus the first matching structure and return immediately
}
}
}
}
dispose() {
this._events.dispose();
this.plugin.dispose();
}
}
@@ -576,52 +605,12 @@ export interface VolumeIsovalueInfo {
export interface LoadTrajectoryParams {
model: { kind: 'model-url', url: string, format?: BuiltInTrajectoryFormat /* mmcif */, isBinary?: boolean }
| { kind: 'model-data', data: string | number[] | ArrayBuffer | Uint8Array, format?: BuiltInTrajectoryFormat /* mmcif */ }
| { kind: 'model-data', data: string | number[] | ArrayBuffer | Uint8Array<ArrayBuffer>, format?: BuiltInTrajectoryFormat /* mmcif */ }
| { kind: 'topology-url', url: string, format: BuiltInTopologyFormat, isBinary?: boolean }
| { kind: 'topology-data', data: string | number[] | ArrayBuffer | Uint8Array, format: BuiltInTopologyFormat },
| { kind: 'topology-data', data: string | number[] | ArrayBuffer | Uint8Array<ArrayBuffer>, format: BuiltInTopologyFormat },
modelLabel?: string,
coordinates: { kind: 'coordinates-url', url: string, format: BuiltInCoordinatesFormat, isBinary?: boolean }
| { kind: 'coordinates-data', data: string | number[] | ArrayBuffer | Uint8Array, format: BuiltInCoordinatesFormat },
| { kind: 'coordinates-data', data: string | number[] | ArrayBuffer | Uint8Array<ArrayBuffer>, format: BuiltInCoordinatesFormat },
coordinatesLabel?: string,
preset?: keyof PresetTrajectoryHierarchy
}
export const ViewerAutoPreset = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-viewer-auto',
display: {
name: 'Automatic (w/ Annotation)', group: 'Annotation',
description: 'Show standard automatic representation but colored by quality assessment (if available in the model).'
},
isApplicable(a) {
return (
!!a.data.models.some(m => QualityAssessment.isApplicable(m, 'pLDDT')) ||
!!a.data.models.some(m => QualityAssessment.isApplicable(m, 'qmean'))
);
},
params: () => StructureRepresentationPresetProvider.CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
const structure = structureCell?.obj?.data;
if (!structureCell || !structure) return {};
if (!!structure.models.some(m => QualityAssessment.isApplicable(m, 'pLDDT'))) {
return await QualityAssessmentPLDDTPreset.apply(ref, params, plugin);
} else if (!!structure.models.some(m => QualityAssessment.isApplicable(m, 'qmean'))) {
return await QualityAssessmentQmeanPreset.apply(ref, params, plugin);
} else if (!!structure.models.some(m => SbNcbrPartialChargesPropertyProvider.isApplicable(m))) {
return await SbNcbrPartialChargesPreset.apply(ref, params, plugin);
} else {
return await PresetStructureRepresentations.auto.apply(ref, params, plugin);
}
}
});
export const PluginExtensions = {
wwPDBStructConn: wwPDBStructConnExtensionFunctions,
mvs: { MVSData, loadMVS },
modelArchive: {
qualityAssessment: {
config: MAQualityAssessmentConfig
}
}
};
}

View File

@@ -0,0 +1,71 @@
/**
* Copyright (c) 2018-2026 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>
* @author Adam Midlik <midlik@gmail.com>
*/
import { ANVILMembraneOrientation } from '../../extensions/anvil/behavior';
import { AssemblySymmetry } from '../../extensions/assembly-symmetry';
import { Backgrounds } from '../../extensions/backgrounds';
import { DebugHelpers } from '../../extensions/debug-helpers';
import { DnatcoNtCs } from '../../extensions/dnatco';
import { G3DFormat } from '../../extensions/g3d/format';
import { GeometryExport } from '../../extensions/geo-export';
import { MAQualityAssessment, MAQualityAssessmentConfig } from '../../extensions/model-archive/quality-assessment/behavior';
import { ModelExport } from '../../extensions/model-export';
import { Mp4Export } from '../../extensions/mp4-export';
import { loadMVS } from '../../extensions/mvs';
import { MolViewSpec } from '../../extensions/mvs/behavior';
import { loadMVSData } from '../../extensions/mvs/components/formats';
import { PDBeStructureQualityReport } from '../../extensions/pdbe';
import { RCSBValidationReport } from '../../extensions/rcsb';
import { SbNcbrPartialCharges, SbNcbrTunnels } from '../../extensions/sb-ncbr';
import { wwPDBChemicalComponentDictionary } from '../../extensions/wwpdb/ccd/behavior';
import { wwPDBStructConnExtensionFunctions } from '../../extensions/wwpdb/struct-conn';
import { ZenodoImport } from '../../extensions/zenodo';
import { PluginSpec } from '../../mol-plugin/spec';
import { MVSData } from '../../extensions/mvs/mvs-data';
import * as MVSUtil from '../../extensions/mvs/util';
export const ExtensionMap = {
// Mol* built-in extensions
'mvs': PluginSpec.Behavior(MolViewSpec),
'backgrounds': PluginSpec.Behavior(Backgrounds),
'debug-helpers': PluginSpec.Behavior(DebugHelpers),
'model-export': PluginSpec.Behavior(ModelExport),
'mp4-export': PluginSpec.Behavior(Mp4Export),
'geo-export': PluginSpec.Behavior(GeometryExport),
'zenodo-import': PluginSpec.Behavior(ZenodoImport),
'wwpdb-chemical-component-dictionary': PluginSpec.Behavior(wwPDBChemicalComponentDictionary),
// 3rd party extensions
'pdbe-structure-quality-report': PluginSpec.Behavior(PDBeStructureQualityReport),
'dnatco-ntcs': PluginSpec.Behavior(DnatcoNtCs),
'assembly-symmetry': PluginSpec.Behavior(AssemblySymmetry),
'rcsb-validation-report': PluginSpec.Behavior(RCSBValidationReport),
'anvil-membrane-orientation': PluginSpec.Behavior(ANVILMembraneOrientation),
'g3d': PluginSpec.Behavior(G3DFormat), // TODO: consider removing this for Mol* 6.0
'ma-quality-assessment': PluginSpec.Behavior(MAQualityAssessment),
'sb-ncbr-partial-charges': PluginSpec.Behavior(SbNcbrPartialCharges),
'tunnels': PluginSpec.Behavior(SbNcbrTunnels),
};
export const PluginExtensions = {
wwPDBStructConn: wwPDBStructConnExtensionFunctions,
mvs: {
MVSData,
createBuilder: MVSData.createBuilder,
loadMVS,
loadMVSData,
util: {
...MVSUtil
}
},
modelArchive: {
qualityAssessment: {
config: MAQualityAssessmentConfig
}
}
};

View File

@@ -28,13 +28,14 @@
}
#app {
position: absolute;
left: 100px;
top: 100px;
width: 800px;
height: 600px;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
</style>
<link rel="stylesheet" type="text/css" href="molstar.css" />
<!-- __MOLSTAR_MANIFEST__ -->
</head>
<body>
<div id="app"></div>
@@ -65,6 +66,7 @@
var powerPreference = getParam('power-preference', '[^&]+').trim().toLowerCase();
var illumination = getParam('illumination', '[^&]+').trim() === '1';
var resolutionMode = getParam('resolution-mode', '[^&]+').trim().toLowerCase();
var viewportShowToggleFullscreen = getParam('show-toggle-fullscreen', '[^&]+').trim() === '1';
// console.log('Available extensions: ', Object.keys(molstar.ExtensionMap));
@@ -72,6 +74,7 @@
disabledExtensions: [], // anything from Object.keys(molstar.ExtensionMap)
layoutShowControls: !hideControls,
viewportShowExpand: false,
viewportShowToggleFullscreen: viewportShowToggleFullscreen,
collapseLeftPanel: collapseLeftPanel,
pdbProvider: pdbProvider || 'pdbe',
emdbProvider: emdbProvider || 'pdbe',
@@ -86,7 +89,7 @@
allowMajorPerformanceCaveat: allowMajorPerformanceCaveat,
powerPreference: powerPreference || 'high-performance',
illumination: illumination,
resolutionMode: resolutionMode || 'auto'
resolutionMode: resolutionMode || 'auto',
}).then(viewer => {
var snapshotId = getParam('snapshot-id', '[^&]+').trim();
if (snapshotId) viewer.setRemoteSnapshot(snapshotId);
@@ -111,8 +114,11 @@
var pdb = getParam('pdb', '[^&]+').trim();
if (pdb) viewer.loadPdb(pdb);
var pdbIhm = getParam('pdb-ihm', '[^&]+').trim();
if (pdbIhm) viewer.loadPdbIhm(pdbIhm);
// support for deprecated pdb-dev param
var pdbDev = getParam('pdb-dev', '[^&]+').trim();
if (pdbDev) viewer.loadPdbDev(pdbDev);
if (pdbDev) viewer.loadPdbIhm(pdbDev);
var emdb = getParam('emdb', '[^&]+').trim();
if (emdb) viewer.loadEmdb(emdb);
@@ -127,8 +133,12 @@
// to aid GC
viewer.dispose();
});
const event = new CustomEvent("molstarViewerCreated", { detail: { viewer } });
window.dispatchEvent(event);
});
</script>
<!-- __MOLSTAR_PWA__ -->
<!-- __MOLSTAR_ANALYTICS__ -->
</body>
</html>

View File

@@ -1,12 +1,16 @@
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2025 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 './mvs.html';
import './embedded.html';
import './favicon.ico';
import './index.html';
require('mol-plugin-ui/skin/light.scss');
import '../../mol-plugin-ui/skin/light.scss';
export * from './lib';
export * from './extensions';
export * from './app';
export * from './presets';

58
src/apps/viewer/lib.ts Normal file
View File

@@ -0,0 +1,58 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import * as Structure from '../../mol-model/structure';
import { DataLoci, EveryLoci, Loci } from '../../mol-model/loci';
import { Volume } from '../../mol-model/volume';
import { Shape, ShapeGroup } from '../../mol-model/shape';
import * as LinearAlgebra3D from '../../mol-math/linear-algebra/3d';
import { PluginContext } from '../../mol-plugin/context';
import { PluginConfig } from '../../mol-plugin/config';
import { PluginBehavior } from '../../mol-plugin/behavior';
import { DefaultPluginSpec, PluginSpec } from '../../mol-plugin/spec';
import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
import { PluginStateObject, PluginStateTransform } from '../../mol-plugin-state/objects';
import { StateTransforms } from '../../mol-plugin-state/transforms';
import { StateActions } from '../../mol-plugin-state/actions';
import { PluginExtensions } from './extensions';
export const lib = {
structure: {
...Structure,
},
volume: {
Volume,
},
shape: {
Shape,
ShapeGroup,
},
loci: {
Loci,
DataLoci,
EveryLoci,
},
math: {
LinearAlgebra: {
...LinearAlgebra3D,
}
},
plugin: {
PluginContext,
PluginConfig,
PluginBehavior,
PluginSpec,
PluginStateObject,
PluginStateTransform,
StateTransforms,
StateActions,
DefaultPluginSpec,
DefaultPluginUISpec,
},
extensions: {
...PluginExtensions
}
};

179
src/apps/viewer/mvs.html Normal file
View File

@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="icon" href="./favicon.ico" type="image/x-icon">
<title>Mol* Viewer MolViewSpec Example</title>
<style>
body {
background: #111318;
}
#app {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
#controls {
position: absolute;
display: flex;
align-items: center;
font-family: sans-serif;
gap: 8px;
left: 10px;
top: 10px;
z-index: 10;
background-color: #111318;
padding: 10px;
color: white;
}
</style>
<link rel="stylesheet" type="text/css" href="theme/dark.css" />
</head>
<body>
<div id="app"></div>
<div id="controls">
<button onmouseenter="interactivy('highlight')" onmouseleave="interactivy('clear-highlight')" onclick="interactivy('select')">Select Residues 45-50</button>
<button onmouseenter="interactivy('highlight')" onmouseleave="interactivy('clear-highlight')" onclick="interactivy('focus')">Focus</button>
<button onclick="interactivy('clear-select')">Clear Selection</button>
<div id="selection-info"></div>
</div>
<script type="text/javascript" src="molstar.js"></script>
<script type="text/javascript">
function interactivy(action) {
if (action === 'clear-highlight') {
viewer.structureInteractivity({ action: 'highlight' });
} else if (action === 'clear-select') {
viewer.structureInteractivity({ action: 'select' });
} else if (action === 'highlight' || action === 'select' || action === 'focus') {
viewer.structureInteractivity({
elements: { beg_auth_seq_id: 45, end_auth_seq_id: 50 },
action,
focusOptions: { extraRadius: 3 }
});
}
}
function clearSelection() {
viewer.structureInteractivity({ action: 'select' });
}
molstar.Viewer.create('app', {
layoutIsExpanded: true,
layoutShowControls: false,
layoutShowRemoteState: false,
layoutShowSequence: true,
layoutShowLog: false,
layoutShowLeftPanel: true,
viewportShowExpand: true,
viewportShowSelectionMode: false,
viewportShowControls: false,
viewportShowAnimation: false,
viewportFocusBehavior: 'secondary-zoom',
viewportBackgroundColor: '#111318',
pdbProvider: 'rcsb',
emdbProvider: 'rcsb',
}).then(viewer => {
// Make the viewer accessible globally for the demo buttons
window.viewer = viewer;
// Build MVS state
const builder = molstar.lib.extensions.mvs.createBuilder();
const structure = builder
.download({ url: 'https://www.ebi.ac.uk/pdbe/entry-files/1cbs.bcif' })
.parse({ format: 'bcif' })
.modelStructure({});
structure
.component({ selector: 'polymer' })
.representation({ type: 'cartoon' })
.color({ color: 'green' });
structure
.component({ selector: 'ligand' })
.representation({ type: 'ball_and_stick' })
.color({ color: '#cc3399' });
// Extra data can be passed to the MVS snapshot via custom state
// and later accessed it using getCurrentMVSSnapshot() (see hover handler below)
// Each node can have custom data as well, but generally could be harder to access
// This example is a little contrived to demonstrate the concept
builder.extendRootCustomState({
extraResidueAnnotations: {
'REA': 'Ligand'
}
})
builder.canvas({
background_color: "#111318",
})
structure.primitives()
.sphere({
center: { label_comp_id: 'REA' },
radius: 3,
custom: { action: 'Action 1' },
})
.label({
text: '1',
position: { label_comp_id: 'REA' },
label_size: 2.5,
label_color: 'blue',
});
structure.primitives()
.sphere({
center: { label_seq_id: 2 },
radius: 3,
custom: { action: 'Action 2' },
})
.label({
text: '2',
position: { label_seq_id: 2 },
label_size: 2.5,
label_color: 'blue',
});
const mvsData = builder.getState();
viewer.loadMvsData(mvsData, 'mvsj');
// Show current residue interaction
viewer.subscribe(viewer.plugin.behaviors.interaction.hover, e => {
const infoElement = document.getElementById('selection-info');
if (!infoElement) return;
if (molstar.lib.structure.StructureElement.Loci.is(e.current.loci)) {
molstar.lib.structure.StructureElement.Loci.forEachLocation(e.current.loci, location => {
const props = molstar.lib.structure.StructureProperties;
let label = `Hovered Residue: ${props.chain.label_asym_id(location)} ${props.residue.label_seq_id(location)}`;
const compId = props.residue.label_comp_id(location);
const snapshot = molstar.lib.extensions.mvs.util.getCurrentMVSSnapshot(viewer.plugin);
if (snapshot && snapshot.root.custom && snapshot.root.custom.extraResidueAnnotations) {
const extra = snapshot.root.custom.extraResidueAnnotations[compId];
if (extra) label += ` (${extra})`;
}
infoElement.innerText = label;
});
} else {
infoElement.innerText = '';
}
});
// Show clicked primitive action
viewer.subscribe(viewer.plugin.behaviors.interaction.click, e => {
const nodes = molstar.lib.extensions.mvs.util.tryGetPrimitivesFromLoci(e.current.loci);
if (nodes?.length) {
alert('Clicked on: ' + (nodes[0].custom?.action || 'unknown'));
}
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2018-2025 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 { AssemblySymmetryConfig } from '../../extensions/assembly-symmetry';
import { G3dProvider } from '../../extensions/g3d/format';
import { SaccharideCompIdMapType } from '../../mol-model/structure/structure/carbohydrates/constants';
import { DataFormatProvider } from '../../mol-plugin-state/formats/provider';
import { PluginConfig, PluginConfigItem } from '../../mol-plugin/config';
import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
import '../../mol-util/polyfill';
import { ObjectKeys } from '../../mol-util/type-helpers';
import { ExtensionMap } from './extensions';
const CustomFormats: [string, DataFormatProvider][] = [
['g3d', G3dProvider] as const
];
export const DefaultViewerOptions = {
customFormats: CustomFormats as [string, DataFormatProvider][],
extensions: ObjectKeys(ExtensionMap),
disabledExtensions: [] as string[],
layoutIsExpanded: true,
layoutShowControls: true,
layoutShowRemoteState: true,
layoutControlsDisplay: 'reactive' as PluginLayoutControlsDisplay,
layoutShowSequence: true,
layoutShowLog: true,
layoutShowLeftPanel: true,
collapseLeftPanel: false,
collapseRightPanel: false,
disableAntialiasing: PluginConfig.General.DisableAntialiasing.defaultValue,
pixelScale: PluginConfig.General.PixelScale.defaultValue,
pickScale: PluginConfig.General.PickScale.defaultValue,
transparency: PluginConfig.General.Transparency.defaultValue,
preferWebgl1: PluginConfig.General.PreferWebGl1.defaultValue,
allowMajorPerformanceCaveat: PluginConfig.General.AllowMajorPerformanceCaveat.defaultValue,
powerPreference: PluginConfig.General.PowerPreference.defaultValue,
resolutionMode: PluginConfig.General.ResolutionMode.defaultValue,
illumination: false,
viewportShowReset: PluginConfig.Viewport.ShowReset.defaultValue,
viewportShowScreenshotControls: PluginConfig.Viewport.ShowScreenshotControls.defaultValue,
viewportShowControls: PluginConfig.Viewport.ShowControls.defaultValue,
viewportShowExpand: PluginConfig.Viewport.ShowExpand.defaultValue,
viewportShowToggleFullscreen: PluginConfig.Viewport.ShowToggleFullscreen.defaultValue,
viewportShowSettings: PluginConfig.Viewport.ShowSettings.defaultValue,
viewportShowSelectionMode: PluginConfig.Viewport.ShowSelectionMode.defaultValue,
viewportShowAnimation: PluginConfig.Viewport.ShowAnimation.defaultValue,
viewportShowTrajectoryControls: PluginConfig.Viewport.ShowTrajectoryControls.defaultValue,
// default: zoom & show structure interaction
// secondary-zoom: zoom only, doesn't use primary mouse button
// disabled: no automatic zoom or interaction on focus
viewportFocusBehavior: 'default' as 'default' | 'secondary-zoom' | 'disabled',
viewportBackgroundColor: undefined as string | undefined,
pluginStateServer: PluginConfig.State.DefaultServer.defaultValue,
volumeStreamingServer: PluginConfig.VolumeStreaming.DefaultServer.defaultValue,
volumeStreamingDisabled: !PluginConfig.VolumeStreaming.Enabled.defaultValue,
pdbProvider: PluginConfig.Download.DefaultPdbProvider.defaultValue,
emdbProvider: PluginConfig.Download.DefaultEmdbProvider.defaultValue,
saccharideCompIdMapType: 'default' as SaccharideCompIdMapType,
rcsbAssemblySymmetryDefaultServerType: AssemblySymmetryConfig.DefaultServerType.defaultValue,
rcsbAssemblySymmetryDefaultServerUrl: AssemblySymmetryConfig.DefaultServerUrl.defaultValue,
rcsbAssemblySymmetryApplyColors: AssemblySymmetryConfig.ApplyColors.defaultValue,
config: [] as [PluginConfigItem, any][],
};
export type ViewerOptions = typeof DefaultViewerOptions;

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { QualityAssessmentPLDDTPreset, QualityAssessmentQmeanPreset } from '../../extensions/model-archive/quality-assessment/behavior';
import { QualityAssessment } from '../../extensions/model-archive/quality-assessment/prop';
import { SbNcbrPartialChargesPreset, SbNcbrPartialChargesPropertyProvider } from '../../extensions/sb-ncbr';
import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
import { StateObjectRef } from '../../mol-state';
export const ViewerAutoPreset = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-viewer-auto',
display: {
name: 'Automatic (w/ Annotation)', group: 'Annotation',
description: 'Show standard automatic representation but colored by quality assessment (if available in the model).'
},
isApplicable(a) {
return (
!!a.data.models.some(m => QualityAssessment.isApplicable(m, 'pLDDT')) ||
!!a.data.models.some(m => QualityAssessment.isApplicable(m, 'qmean'))
);
},
params: () => StructureRepresentationPresetProvider.CommonParams,
async apply(ref, params, plugin) {
const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref);
const structure = structureCell?.obj?.data;
if (!structureCell || !structure) return {};
if (!!structure.models.some(m => QualityAssessment.isApplicable(m, 'pLDDT'))) {
return await QualityAssessmentPLDDTPreset.apply(ref, params, plugin);
} else if (!!structure.models.some(m => QualityAssessment.isApplicable(m, 'qmean'))) {
return await QualityAssessmentQmeanPreset.apply(ref, params, plugin);
} else if (!!structure.models.some(m => SbNcbrPartialChargesPropertyProvider.isApplicable(m))) {
return await SbNcbrPartialChargesPreset.apply(ref, params, plugin);
} else {
return await PresetStructureRepresentations.auto.apply(ref, params, plugin);
}
}
});

View File

@@ -0,0 +1,7 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import '../../../mol-plugin-ui/skin/blue.scss';

View File

@@ -0,0 +1,7 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import '../../../mol-plugin-ui/skin/dark.scss';

View File

@@ -0,0 +1,7 @@
/**
* Copyright (c) 2025 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import '../../../mol-plugin-ui/skin/light.scss';

View File

@@ -1,17 +1,16 @@
#!/usr/bin/env node
/**
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Josh McMenemy <josh.mcmenemy@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as argparse from 'argparse';
import * as path from 'path';
import util from 'util';
import fs from 'fs';
require('util.promisify').shim();
const writeFile = util.promisify(fs.writeFile);
const writeFileAsync = fs.promises.writeFile;
import { DatabaseCollection } from '../../mol-data/db';
import { CCD_Schema } from '../../mol-io/reader/cif/schema/ccd';
@@ -32,7 +31,7 @@ function extractIonNames(ccd: DatabaseCollection<CCD_Schema>) {
function writeIonNamesFile(filePath: string, ionNames: string[]) {
const output = `/**
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Code-generated ion names params file. Names extracted from CCD components.
*
@@ -41,7 +40,7 @@ function writeIonNamesFile(filePath: string, ionNames: string[]) {
export const IonNames = new Set(${JSON.stringify(ionNames).replace(/"/g, "'").replace(/,/g, ', ')});
`;
writeFile(filePath, output);
writeFileAsync(filePath, output);
}
async function run(out: string, options = DefaultDataOptions) {

View File

@@ -1,16 +1,15 @@
#!/usr/bin/env node
/**
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2022-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as argparse from 'argparse';
import * as path from 'path';
import util from 'util';
import fs from 'fs';
require('util.promisify').shim();
const writeFile = util.promisify(fs.writeFile);
const writeFileAsync = fs.promises.writeFile;
import { DatabaseCollection } from '../../mol-data/db';
import { CCD_Schema } from '../../mol-io/reader/cif/schema/ccd';
@@ -44,7 +43,7 @@ function writeSaccharideNamesFile(filePath: string, ionNames: string[]) {
export const SaccharideNames = new Set(${JSON.stringify(ionNames).replace(/"/g, "'").replace(/,/g, ', ')});
`;
writeFile(filePath, output);
writeFileAsync(filePath, output);
}
async function run(out: string, options = DefaultDataOptions) {

View File

@@ -1,16 +1,15 @@
#!/usr/bin/env node
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as argparse from 'argparse';
import * as util from 'util';
import * as path from 'path';
import * as fs from 'fs';
require('util.promisify').shim();
const writeFile = util.promisify(fs.writeFile);
const writeFileAsync = fs.promises.writeFile;
import { Database, Table, DatabaseCollection } from '../../mol-data/db';
import { CCD_Schema } from '../../mol-io/reader/cif/schema/ccd';
@@ -250,14 +249,14 @@ async function run(out: string, binary = false, options = DefaultDataOptions, cc
if (!fs.existsSync(path.dirname(out))) {
fs.mkdirSync(path.dirname(out));
}
writeFile(out, ccbCif);
writeFileAsync(out, ccbCif);
if (!!ccaOut) {
const ccaCif = getEncodedCif(CCA_TABLE_NAME, atoms, binary);
if (!fs.existsSync(path.dirname(ccaOut))) {
fs.mkdirSync(path.dirname(ccaOut));
}
writeFile(ccaOut, ccaCif);
writeFileAsync(ccaOut, ccaCif);
}
}

View File

@@ -1,17 +1,15 @@
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as util from 'util';
import * as path from 'path';
import * as fs from 'fs';
import * as zlib from 'zlib';
import fetch from 'node-fetch';
require('util.promisify').shim();
const readFile = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);
const readFileAsync = fs.promises.readFile;
const writeFileAsync = fs.promises.writeFile;
import { Progress } from '../../mol-task';
import { Database } from '../../mol-data/db';
@@ -27,9 +25,9 @@ export async function ensureAvailable(path: string, url: string, forceDownload =
fs.mkdirSync(DATA_DIR);
}
if (url.endsWith('.gz')) {
await writeFile(path, zlib.gunzipSync(await data.buffer()));
await writeFileAsync(path, zlib.gunzipSync(await data.arrayBuffer()));
} else {
await writeFile(path, await data.text());
await writeFileAsync(path, await data.text());
}
console.log(`done downloading ${url}`);
}
@@ -41,7 +39,7 @@ export async function ensureDataAvailable(options: DataOptions) {
}
export async function readFileAsCollection<S extends Database.Schema>(path: string, schema: S) {
const parsed = await parseCif(await readFile(path, 'utf8'));
const parsed = await parseCif(await readFileAsync(path, 'utf8'));
return CIF.toDatabaseCollection(schema, parsed.result);
}

View File

@@ -1,8 +1,9 @@
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import { CIF, CifCategory, getCifFieldType, CifField, CifFile } from '../../mol-io/reader/cif';
@@ -15,30 +16,27 @@ import { classifyFloatArray, classifyIntArray } from '../../mol-io/common/binary
import { BinaryEncodingProvider } from '../../mol-io/writer/cif/encoder/binary';
import { Category } from '../../mol-io/writer/cif/encoder';
import { ReaderResult } from '../../mol-io/reader/result';
import { utf8ReadLong } from '../../mol-io/common/utf8';
function showProgress(p: Progress) {
process.stdout.write(`\r${new Array(80).join(' ')}`);
process.stdout.write(`\r${Progress.format(p)}`);
}
const readFileAsync = util.promisify(fs.readFile);
const readFileAsync = fs.promises.readFile;
const unzipAsync = util.promisify<zlib.InputType, Buffer>(zlib.unzip);
async function readFile(ctx: RuntimeContext, filename: string): Promise<ReaderResult<CifFile>> {
const isGz = /\.gz$/i.test(filename);
if (filename.match(/\.bcif/)) {
let input = await readFileAsync(filename);
if (isGz) input = await unzipAsync(input);
if (isGz) input = await unzipAsync(input) as NonSharedBuffer;
return await CIF.parseBinary(new Uint8Array(input)).runInContext(ctx);
} else {
let str: string;
if (isGz) {
const data = await unzipAsync(await readFileAsync(filename));
str = data.toString('utf8');
} else {
str = await readFileAsync(filename, 'utf8');
}
return await CIF.parseText(str).runInContext(ctx);
const data = isGz ? await unzipAsync(await readFileAsync(filename)) : await readFileAsync(filename);
const str = utf8ReadLong(data);
const cif = await CIF.parseText(str).runInContext(ctx);
return cif;
}
}

View File

@@ -12,7 +12,6 @@ import * as fs from 'fs';
import * as zlib from 'zlib';
import { convert } from './converter';
require('util.promisify').shim();
async function process(srcPath: string, outPath: string, configPath?: string, filterPath?: string) {
const config = configPath ? JSON.parse(fs.readFileSync(configPath, 'utf8')) : void 0;

View File

@@ -1,14 +1,14 @@
#!/usr/bin/env node
/**
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as argparse from 'argparse';
import * as fs from 'fs';
import * as path from 'path';
import fetch from 'node-fetch';
import { parseCsv } from '../../mol-io/reader/csv/parser';
import { CifFrame, CifBlock } from '../../mol-io/reader/cif';
@@ -166,9 +166,9 @@ const MA_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/ModelCIF/master/dist
const CIF_CORE_DIC_PATH = `${DIC_DIR}/cif_core.dic`;
const CIF_CORE_DIC_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/cif_core.dic';
const CIF_CORE_ENUM_PATH = `${DIC_DIR}/templ_enum.cif`;
const CIF_CORE_ENUM_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/templ_enum.cif';
const CIF_CORE_ENUM_URL = 'https://raw.githubusercontent.com/COMCIFS/Enumeration_Templates/refs/heads/main/templ_enum.cif';
const CIF_CORE_ATTR_PATH = `${DIC_DIR}/templ_attr.cif`;
const CIF_CORE_ATTR_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/templ_attr.cif';
const CIF_CORE_ATTR_URL = 'https://raw.githubusercontent.com/COMCIFS/Attribute_Templates/refs/heads/main/templ_attr.cif';
const parser = new argparse.ArgumentParser({
add_help: true,

View File

@@ -93,6 +93,7 @@ export function getFieldType(type: string, description: string, values?: string[
case 'Implied':
case 'Word':
case 'Uri':
case 'Iri':
return wrapContainer('str', ',', description, container);
case 'Real':
return wrapContainer('float', ',', description, container);

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -65,7 +65,9 @@ function getTypeDef(c: Column): string {
case 'float': return 'float';
case 'coord': return 'coord';
case 'enum':
return `Aliased<'${c.values.map(v => v.replace(/'/g, '\\\'')).join(`' | '`)}'>(${c.subType})`;
return c.subType === 'int'
? `Aliased<${c.values.join(' | ')}>(${c.subType})`
: `Aliased<'${c.values.map(v => v.replace(/'/g, '\\\'')).join(`' | '`)}'>(${c.subType})`;
case 'matrix':
return `Matrix(${c.rows}, ${c.columns})`;
case 'vector':

View File

@@ -1,14 +1,14 @@
#!/usr/bin/env node
/**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as argparse from 'argparse';
import * as fs from 'fs';
import * as path from 'path';
import fetch from 'node-fetch';
import { UniqueArray } from '../../mol-data/generic';
const LIPIDS_DIR = path.resolve(__dirname, '../../../../build/lipids/');
@@ -33,6 +33,14 @@ async function ensureLipidsAvailable() { await ensureAvailable(MARTINI_LIPIDS_PA
const extraLipids = ['DMPC'];
const v2lipids = ['DAPC', 'DBPC', 'DFPC', 'DGPC', 'DIPC', 'DLPC', 'DNPC', 'DOPC', 'DPPC', 'DRPC', 'DTPC', 'DVPC', 'DXPC', 'DYPC', 'LPPC', 'PAPC', 'PEPC', 'PGPC', 'PIPC', 'POPC', 'PRPC', 'PUPC', 'DAPE', 'DBPE', 'DFPE', 'DGPE', 'DIPE', 'DLPE', 'DNPE', 'DOPE', 'DPPE', 'DRPE', 'DTPE', 'DUPE', 'DVPE', 'DXPE', 'DYPE', 'LPPE', 'PAPE', 'PGPE', 'PIPE', 'POPE', 'PQPE', 'PRPE', 'PUPE', 'DAPS', 'DBPS', 'DFPS', 'DGPS', 'DIPS', 'DLPS', 'DNPS', 'DOPS', 'DPPS', 'DRPS', 'DTPS', 'DUPS', 'DVPS', 'DXPS', 'DYPS', 'LPPS', 'PAPS', 'PGPS', 'PIPS', 'POPS', 'PQPS', 'PRPS', 'PUPS', 'DAPG', 'DBPG', 'DFPG', 'DGPG', 'DIPG', 'DLPG', 'DNPG', 'DOPG', 'DPPG', 'DRPG', 'DTPG', 'DVPG', 'DXPG', 'DYPG', 'LPPG', 'PAPG', 'PGPG', 'PIPG', 'POPG', 'PRPG', 'DAPA', 'DBPA', 'DFPA', 'DGPA', 'DIPA', 'DLPA', 'DNPA', 'DOPA', 'DPPA', 'DRPA', 'DTPA', 'DVPA', 'DXPA', 'DYPA', 'LPPA', 'PAPA', 'PGPA', 'PIPA', 'POPA', 'PRPA', 'PUPA', 'DPP', 'DPPI', 'PAPI', 'PIPI', 'POP', 'POPI', 'PUPI', 'PVP', 'PVPI', 'PADG', 'PIDG', 'PODG', 'PUDG', 'PVDG', 'APC', 'CPC', 'IPC', 'LPC', 'OPC', 'PPC', 'TPC', 'UPC', 'VPC', 'BNSM', 'DBSM', 'DPSM', 'DXSM', 'PGSM', 'PNSM', 'POSM', 'PVSM', 'XNSM', 'DPCE', 'DXCE', 'PNCE', 'XNCE'];
const amberLipids = [
// acyl chains
'PA', 'ST', 'OL', 'LEO', 'LEN', 'AR', 'DHA',
// head groups
'PC', 'PE', 'PS', 'PH-', 'P2-', 'PGR', 'PGS', 'PI',
// other
'CHL'
];
async function run(out: string) {
await ensureLipidsAvailable();
@@ -55,13 +63,17 @@ async function run(out: string) {
UniqueArray.add(lipids, v, v);
}
for (const v of amberLipids) {
UniqueArray.add(lipids, v, v);
}
const lipidNames = JSON.stringify(lipids.array);
if (out) {
const output = `/**
* Copyright (c) 2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Code-generated lipid params file. Names extracted from Martini FF lipids itp.
* Code-generated lipid params file. Names from Martini FF and Amber.
*
* @author molstar/lipid-params cli
*/

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env node
/**
* Copyright (c) 2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Adam Midlik <midlik@gmail.com>
*
* Command-line application for converting MolViewSpec MVSJ into MSVX files
* Build: npm run build
* Run: node lib/commonjs/cli/mvs/mvs-mvsj-to-mvsx -i examples/mvs/1cbs.mvsj -o tmp/1cbs.mvsx
*/
import { ArgumentParser } from 'argparse';
import fs from 'fs';
import { MVSData } from '../../extensions/mvs/mvs-data';
import { setFSModule } from '../../mol-util/data-source';
setFSModule(fs);
/** Command line argument values for `main` */
interface Args {
input: string[],
output: string[] | undefined,
base_uri: string | undefined,
skip_external: boolean,
}
/** Return parsed command line arguments for `main` */
function parseArguments(): Args {
const parser = new ArgumentParser({ description: 'Command-line application for converting MolViewSpec MVSJ into MSVX files' });
parser.add_argument('-i', '--input', { required: true, nargs: '+', help: 'Input file(s) in .mvsj format.' });
parser.add_argument('-o', '--output', { required: false, nargs: '+', help: 'File path(s) for output files in .mvsx format (one output path for each input file). If ommitted, filenames will be created automatically by replacing file extension.' });
parser.add_argument('--base-uri', { help: 'Base URI/path used to resolve relative URIs in the input file (default: path of the input file itself). Use `--base-uri .` for using the current working directory as base URI.' });
parser.add_argument('--skip-external', { action: 'store_true', help: 'Do not include external resources (i.e. absolute URIs) in the MVSX.' });
const args: Args = parser.parse_args();
if (args.output && args.output.length !== args.input.length) {
parser.error(`argument: --output: must specify the same number of input and output file paths (specified ${args.input.length} input path${args.input.length !== 1 ? 's' : ''} but ${args.output.length} output path${args.output.length !== 1 ? 's' : ''})`);
}
return { ...args };
}
/** Main workflow for converting MVSJ to MVSX files. */
async function main(args: Args): Promise<void> {
const cache = {};
for (let i = 0; i < args.input.length; i++) {
const input = args.input[i];
const output = args.output?.[i] ?? input.replace(/(\.mvsj)?$/i, '.mvsx');
console.log(`Processing ${input} -> ${output}`);
const mvsj = fs.readFileSync(input, { encoding: 'utf8' });
const mvsData = MVSData.fromMVSJ(mvsj);
const mvsx = await MVSData.toMVSX(mvsData, {
baseUri: args.base_uri ?? input,
skipExternal: args.skip_external,
cache,
});
fs.writeFileSync(output, mvsx);
}
}
main(parseArguments());

View File

@@ -11,7 +11,7 @@
*/
import { ArgumentParser } from 'argparse';
import { treeSchemaToMarkdown, treeSchemaToString } from '../../extensions/mvs/tree/generic/tree-schema';
import { treeSchemaToMarkdown, treeSchemaToString } from '../../extensions/mvs/tree/generic/tree-validation';
import { MVSTreeSchema } from '../../extensions/mvs/tree/mvs/mvs-tree';

View File

@@ -100,7 +100,7 @@ async function main(args: Args): Promise<void> {
} else {
throw new Error(`Input file name must end with .mvsj or .mvsx: ${input}`);
}
await loadMVS(plugin, mvsData, { sanityChecks: true, replaceExisting: true, sourceUrl: sourceUrl, extensions: args.no_extensions ? [] : undefined });
await loadMVS(plugin, mvsData, { sanityChecks: true, sourceUrl: sourceUrl, extensions: args.no_extensions ? [] : undefined });
fs.mkdirSync(path.dirname(output), { recursive: true });
if (args.molj) {

View File

@@ -43,7 +43,7 @@ function paramInfo(param: PD.Any, offset: number): string {
}
}
function oToS(options: readonly (readonly [string, string] | readonly [string, string, string | undefined])[]) {
function oToS(options: readonly PD.SelectOption<any>[]) {
return options.map(o => `'${o[0]}'`).join(', ');
}

View File

@@ -1,18 +1,16 @@
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as util from 'util';
import * as fs from 'fs';
import fetch from 'node-fetch';
require('util.promisify').shim();
import { CIF } from '../../mol-io/reader/cif';
import { Progress } from '../../mol-task';
const readFileAsync = util.promisify(fs.readFile);
const readFileAsync = fs.promises.readFile;
async function readFile(path: string) {
if (path.match(/\.bcif$/)) {

View File

@@ -7,7 +7,6 @@
*/
import * as argparse from 'argparse';
require('util.promisify').shim();
import { CifFrame } from '../../mol-io/reader/cif';
import { Model, Structure, StructureElement, Unit, StructureProperties, UnitRing, Trajectory } from '../../mol-model/structure';

View File

@@ -1,13 +1,14 @@
#!/usr/bin/env node
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2026 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>
* @author Paul Pillot <paul.pillot@tandemai.com>
*/
import * as fs from 'fs';
import * as argparse from 'argparse';
import * as util from 'util';
import { Volume } from '../../mol-model/volume';
import { downloadCif } from './helpers';
@@ -19,8 +20,7 @@ import { createVolumeIsosurfaceMesh } from '../../mol-repr/volume/isosurface';
import { Theme } from '../../mol-theme/theme';
import { volumeFromDensityServerData, DscifFormat } from '../../mol-model-formats/volume/density-server';
require('util.promisify').shim();
const writeFileAsync = util.promisify(fs.writeFile);
const writeFileAsync = fs.promises.writeFile;
async function getVolume(url: string): Promise<Volume> {
const cif = await downloadCif(url, true);
@@ -38,7 +38,7 @@ function print(volume: Volume) {
}
async function doMesh(volume: Volume, filename: string) {
const mesh = await Task.create('', runtime => createVolumeIsosurfaceMesh({ runtime }, volume, -1, Theme.createEmpty(), { isoValue: Volume.IsoValue.absolute(1.5) })).run();
const mesh = await Task.create('', runtime => createVolumeIsosurfaceMesh({ runtime }, volume, -1, Theme.createEmpty(), { isoValue: Volume.IsoValue.absolute(1.5), wrap: 'auto', floodfill: 'off' })).run();
console.log({ vc: mesh.vertexCount, tc: mesh.triangleCount });
// Export the mesh in OBJ format.

View File

@@ -47,8 +47,8 @@
<div id="app"></div>
<div id='controls'></div>
<div id='sponsor'>
<a href='https://www.entos.ai/envision' target="_blank" rel="noopener">
<svg class="makeStyles-root-46" viewBox="0 0 190 36" xmlns="http://www.w3.org/2000/svg"><path d="M32.2591 28.6707C32.2591 32.3914 29.2421 35.407 25.5214 35.407C22.0752 35.407 19.2338 32.8206 18.8325 29.4831V29.4775C18.8143 29.3312 18.8018 29.1835 18.7934 29.0344C18.7934 29.0316 18.7921 29.0274 18.7921 29.0246V29.0177C18.7865 28.902 18.7837 28.7864 18.7837 28.6707C18.7837 26.2557 20.0532 24.1389 21.9609 22.9503C21.9623 22.9489 21.9651 22.9489 21.9665 22.9475C22.0933 22.8666 22.2243 22.7914 22.3581 22.7203C22.3581 22.7203 22.3595 22.7203 22.3595 22.7189C23.3029 22.2173 24.3787 21.933 25.5214 21.933C29.2421 21.933 32.2591 24.9486 32.2591 28.6707Z"></path><path d="M25.5214 14.0692C29.2421 14.0692 32.2591 11.0522 32.2591 7.33146C32.2591 3.61074 29.2421 0.59375 25.5214 0.59375C22.0529 0.59375 19.1962 3.21637 18.8255 6.58592C18.8185 6.67092 18.8116 6.75454 18.8018 6.83815C18.7893 7.00119 18.7837 7.16563 18.7837 7.33146C18.7837 9.73669 20.0434 11.8465 21.94 13.038C22.0891 13.116 22.2355 13.201 22.3776 13.2916C22.3783 13.2923 22.379 13.2926 22.3797 13.293C22.3804 13.2933 22.3811 13.2937 22.3818 13.2944C23.3196 13.7891 24.3871 14.0692 25.5214 14.0692Z"></path><path d="M19.3645 12.4113C20.2926 12.4113 21.1694 12.638 21.94 13.038C20.0434 11.8465 18.7837 9.73669 18.7837 7.33146C18.7837 7.16563 18.7893 7.00119 18.8018 6.83815C18.4688 9.76455 16.1385 12.0866 13.2065 12.4044C13.8545 13.1193 14.3785 13.9484 14.745 14.857C15.7497 13.3798 17.4443 12.4113 19.3645 12.4113Z"></path><path d="M14.7312 21.1249V21.1236C14.1279 20.2331 13.7767 19.1587 13.7767 18.0007V17.9728C13.7767 15.3084 12.2285 13.0035 9.9835 11.911C9.98141 11.9103 9.97967 11.9096 9.97793 11.9089C9.97619 11.9082 9.97444 11.9075 9.97235 11.9068C9.96817 11.904 9.96538 11.9026 9.9612 11.9012C9.95981 11.9012 9.95981 11.8998 9.95981 11.8998C9.9417 11.8915 9.92394 11.8831 9.90618 11.8747C9.8884 11.8664 9.87063 11.858 9.85251 11.8497C9.82046 11.8343 9.78701 11.819 9.75357 11.8051L9.74521 11.8009C8.91745 11.4372 8.0019 11.2351 7.03898 11.2351C3.31826 11.2351 0.30127 14.2521 0.30127 17.9728C0.30127 21.6935 3.31826 24.7105 7.03898 24.7105C7.98797 24.7105 8.89098 24.514 9.71037 24.1601C9.71246 24.1594 9.7142 24.1583 9.71594 24.1573C9.71768 24.1562 9.71943 24.1552 9.72152 24.1545C9.8107 24.1169 9.8985 24.0765 9.9849 24.0333L9.98629 24.0319C10.7625 23.6919 11.6181 23.5037 12.5197 23.5037C12.7524 23.5037 12.9824 23.5163 13.2081 23.54C13.2082 23.5399 13.2081 23.54 13.2081 23.54C15.0168 23.7365 16.5971 24.695 17.6185 26.0885C17.9195 25.1688 18.3752 24.3201 18.9563 23.5732C17.1964 23.4464 15.6635 22.5058 14.7312 21.1249Z"></path><g clip-path="url(#clip0)"><path d="M106.391 18.0021C106.391 11.3724 101.039 6 94.4389 6H88.4585C81.8581 6 76.5061 11.3724 76.5061 18.0021V30.0042H81.2845V18.0021C81.2845 14.0268 84.4941 10.8008 88.4585 10.8008H94.4347C98.395 10.8008 101.609 14.0226 101.609 18.0021V30.0042H106.391V18.0021Z"></path><path d="M149.432 6H142.258C135.653 6 130.301 11.3724 130.301 18.0021C130.301 24.6319 135.653 30.0042 142.258 30.0042H149.432C156.036 30.0042 161.388 24.6319 161.388 18.0021C161.388 11.3724 156.032 6 149.432 6ZM149.432 25.1992H142.258C138.297 25.1992 135.084 21.9774 135.084 17.9979C135.084 14.0183 138.293 10.7966 142.258 10.7966H149.432C153.392 10.7966 156.606 14.0183 156.606 17.9979C156.606 21.9774 153.392 25.1992 149.432 25.1992Z"></path><path d="M74.1151 25.1992H58.5736C55.4526 25.1992 52.804 23.1924 51.8171 20.3983H74.1151V17.9979C74.1151 17.1808 74.1868 16.3807 74.3175 15.5975H51.8171C52.804 12.8033 55.4526 10.7966 58.5736 10.7966H76.0383C77.1475 8.87458 78.6911 7.22773 80.5299 6H58.5736C51.969 6 46.6169 11.3724 46.6169 18.0021C46.6169 24.6276 51.969 30 58.5736 30H74.1151V25.1992Z"></path><path d="M120.74 6H115.958H102.369C104.212 7.22773 105.751 8.87458 106.861 10.8008H115.958V30H120.74V10.8008H129.838C130.947 8.87458 132.486 7.22773 134.329 6H120.74Z"></path><path d="M182.906 15.6017H169.756C168.436 15.6017 167.365 14.5264 167.365 13.2013C167.365 11.8762 168.436 10.8008 169.756 10.8008H188.882V6H169.756C165.796 6 162.582 9.22173 162.582 13.2013C162.582 17.1808 165.791 20.4025 169.756 20.4025H182.906C184.226 20.4025 185.297 21.4779 185.297 22.803C185.297 24.1281 184.226 25.2034 182.906 25.2034H161.852C160.743 27.1297 159.199 28.7765 157.361 30.0042H182.906C186.866 30.0042 190.08 26.7825 190.08 22.803C190.08 18.8234 186.866 15.6017 182.906 15.6017Z"></path></g><defs><clipPath id="clip0"><rect width="190" height="24" fill="white" transform="translate(0 6)"></rect></clipPath></defs></svg>
<a href='https://www.iambic-envision.com/' target="_blank" rel="noopener">
<svg viewBox="0 0 190 36" xmlns="http://www.w3.org/2000/svg"><path d="M32.2591 28.6707C32.2591 32.3914 29.2421 35.407 25.5214 35.407C22.0752 35.407 19.2338 32.8206 18.8325 29.4831V29.4775C18.8143 29.3312 18.8018 29.1835 18.7934 29.0344C18.7934 29.0316 18.7921 29.0274 18.7921 29.0246V29.0177C18.7865 28.902 18.7837 28.7864 18.7837 28.6707C18.7837 26.2557 20.0532 24.1389 21.9609 22.9503C21.9623 22.9489 21.9651 22.9489 21.9665 22.9475C22.0933 22.8666 22.2243 22.7914 22.3581 22.7203C22.3581 22.7203 22.3595 22.7203 22.3595 22.7189C23.3029 22.2173 24.3787 21.933 25.5214 21.933C29.2421 21.933 32.2591 24.9486 32.2591 28.6707Z"></path><path d="M25.5214 14.0692C29.2421 14.0692 32.2591 11.0522 32.2591 7.33146C32.2591 3.61074 29.2421 0.59375 25.5214 0.59375C22.0529 0.59375 19.1962 3.21637 18.8255 6.58592C18.8185 6.67092 18.8116 6.75454 18.8018 6.83815C18.7893 7.00119 18.7837 7.16563 18.7837 7.33146C18.7837 9.73669 20.0434 11.8465 21.94 13.038C22.0891 13.116 22.2355 13.201 22.3776 13.2916C22.3783 13.2923 22.379 13.2926 22.3797 13.293C22.3804 13.2933 22.3811 13.2937 22.3818 13.2944C23.3196 13.7891 24.3871 14.0692 25.5214 14.0692Z"></path><path d="M19.3645 12.4113C20.2926 12.4113 21.1694 12.638 21.94 13.038C20.0434 11.8465 18.7837 9.73669 18.7837 7.33146C18.7837 7.16563 18.7893 7.00119 18.8018 6.83815C18.4688 9.76455 16.1385 12.0866 13.2065 12.4044C13.8545 13.1193 14.3785 13.9484 14.745 14.857C15.7497 13.3798 17.4443 12.4113 19.3645 12.4113Z"></path><path d="M14.7312 21.1249V21.1236C14.1279 20.2331 13.7767 19.1587 13.7767 18.0007V17.9728C13.7767 15.3084 12.2285 13.0035 9.9835 11.911C9.98141 11.9103 9.97967 11.9096 9.97793 11.9089C9.97619 11.9082 9.97444 11.9075 9.97235 11.9068C9.96817 11.904 9.96538 11.9026 9.9612 11.9012C9.95981 11.9012 9.95981 11.8998 9.95981 11.8998C9.9417 11.8915 9.92394 11.8831 9.90618 11.8747C9.8884 11.8664 9.87063 11.858 9.85251 11.8497C9.82046 11.8343 9.78701 11.819 9.75357 11.8051L9.74521 11.8009C8.91745 11.4372 8.0019 11.2351 7.03898 11.2351C3.31826 11.2351 0.30127 14.2521 0.30127 17.9728C0.30127 21.6935 3.31826 24.7105 7.03898 24.7105C7.98797 24.7105 8.89098 24.514 9.71037 24.1601C9.71246 24.1594 9.7142 24.1583 9.71594 24.1573C9.71768 24.1562 9.71943 24.1552 9.72152 24.1545C9.8107 24.1169 9.8985 24.0765 9.9849 24.0333L9.98629 24.0319C10.7625 23.6919 11.6181 23.5037 12.5197 23.5037C12.7524 23.5037 12.9824 23.5163 13.2081 23.54C13.2082 23.5399 13.2081 23.54 13.2081 23.54C15.0168 23.7365 16.5971 24.695 17.6185 26.0885C17.9195 25.1688 18.3752 24.3201 18.9563 23.5732C17.1964 23.4464 15.6635 22.5058 14.7312 21.1249Z"></path><g clip-path="url(#clip0)"><path d="M106.391 18.0021C106.391 11.3724 101.039 6 94.4389 6H88.4585C81.8581 6 76.5061 11.3724 76.5061 18.0021V30.0042H81.2845V18.0021C81.2845 14.0268 84.4941 10.8008 88.4585 10.8008H94.4347C98.395 10.8008 101.609 14.0226 101.609 18.0021V30.0042H106.391V18.0021Z"></path><path d="M149.432 6H142.258C135.653 6 130.301 11.3724 130.301 18.0021C130.301 24.6319 135.653 30.0042 142.258 30.0042H149.432C156.036 30.0042 161.388 24.6319 161.388 18.0021C161.388 11.3724 156.032 6 149.432 6ZM149.432 25.1992H142.258C138.297 25.1992 135.084 21.9774 135.084 17.9979C135.084 14.0183 138.293 10.7966 142.258 10.7966H149.432C153.392 10.7966 156.606 14.0183 156.606 17.9979C156.606 21.9774 153.392 25.1992 149.432 25.1992Z"></path><path d="M74.1151 25.1992H58.5736C55.4526 25.1992 52.804 23.1924 51.8171 20.3983H74.1151V17.9979C74.1151 17.1808 74.1868 16.3807 74.3175 15.5975H51.8171C52.804 12.8033 55.4526 10.7966 58.5736 10.7966H76.0383C77.1475 8.87458 78.6911 7.22773 80.5299 6H58.5736C51.969 6 46.6169 11.3724 46.6169 18.0021C46.6169 24.6276 51.969 30 58.5736 30H74.1151V25.1992Z"></path><path d="M120.74 6H115.958H102.369C104.212 7.22773 105.751 8.87458 106.861 10.8008H115.958V30H120.74V10.8008H129.838C130.947 8.87458 132.486 7.22773 134.329 6H120.74Z"></path><path d="M182.906 15.6017H169.756C168.436 15.6017 167.365 14.5264 167.365 13.2013C167.365 11.8762 168.436 10.8008 169.756 10.8008H188.882V6H169.756C165.796 6 162.582 9.22173 162.582 13.2013C162.582 17.1808 165.791 20.4025 169.756 20.4025H182.906C184.226 20.4025 185.297 21.4779 185.297 22.803C185.297 24.1281 184.226 25.2034 182.906 25.2034H161.852C160.743 27.1297 159.199 28.7765 157.361 30.0042H182.906C186.866 30.0042 190.08 26.7825 190.08 22.803C190.08 18.8234 186.866 15.6017 182.906 15.6017Z"></path></g><defs><clipPath id="clip0"><rect width="190" height="24" fill="white" transform="translate(0 6)"></rect></clipPath></defs></svg>
<div>
Entos Envision
</div>

View File

@@ -24,7 +24,7 @@ import { ParamDefinition } from '../../mol-util/param-definition';
import { mountControls } from './controls';
import { DemoMoleculeSDF, DemoOrbitals } from './example-data';
import './index.html';
require('mol-plugin-ui/skin/light.scss');
import '../../mol-plugin-ui/skin/light.scss';
import { setDebugMode, setTimingMode, consoleStats } from '../../mol-util/debug';

Some files were not shown because too many files have changed in this diff Show More