mirror of
https://github.com/molstar/molstar.git
synced 2026-06-05 14:04:36 +08:00
Compare commits
95 Commits
v3.0.0-dev
...
v3.0.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddc4d8e867 | ||
|
|
7cded03598 | ||
|
|
744b04edc6 | ||
|
|
f2119b1d0b | ||
|
|
b4783909d7 | ||
|
|
fe5f841ab8 | ||
|
|
2c3f0dbc97 | ||
|
|
224fd1733f | ||
|
|
1f262ee422 | ||
|
|
df3bcdd05a | ||
|
|
d5d08542ed | ||
|
|
564a360c8f | ||
|
|
fe0d4dc11e | ||
|
|
812eb0efa9 | ||
|
|
10d0bf293a | ||
|
|
ce2544b9f3 | ||
|
|
1964de1e44 | ||
|
|
20c9d2cc41 | ||
|
|
3b1513adc0 | ||
|
|
eaa60fc5cd | ||
|
|
ce1e3960a2 | ||
|
|
176f80ea9b | ||
|
|
28c9dc8286 | ||
|
|
2135f76441 | ||
|
|
5637a23153 | ||
|
|
2818389741 | ||
|
|
805f772696 | ||
|
|
308bbc1ea0 | ||
|
|
4a248b5591 | ||
|
|
704a9a111d | ||
|
|
a6befc5509 | ||
|
|
9e7aa4226d | ||
|
|
7a25699c23 | ||
|
|
901ae7f6d6 | ||
|
|
c57a4cdf6e | ||
|
|
18573e17f0 | ||
|
|
5bc7ffa8a7 | ||
|
|
430cc83259 | ||
|
|
3cd3afb775 | ||
|
|
93215b6beb | ||
|
|
694261c19c | ||
|
|
58ce1f6498 | ||
|
|
47c4353eb9 | ||
|
|
d82cd3a8fe | ||
|
|
8f06b603e6 | ||
|
|
0865c1b7fb | ||
|
|
c8c32b89c1 | ||
|
|
658c789906 | ||
|
|
c9ad7fce5b | ||
|
|
720a8a440f | ||
|
|
84fe2d2502 | ||
|
|
6f159c592f | ||
|
|
beff1ecb3e | ||
|
|
e4f630dbef | ||
|
|
ccaf18af04 | ||
|
|
2b72098f95 | ||
|
|
b32546bea7 | ||
|
|
b9b0413e9f | ||
|
|
1d29b4627f | ||
|
|
bd44c76709 | ||
|
|
06b4761f2b | ||
|
|
daa3d1dbaa | ||
|
|
5490d5ceb5 | ||
|
|
cf3c1cfcce | ||
|
|
be2607ae84 | ||
|
|
e2966241e8 | ||
|
|
447792b1ef | ||
|
|
1cbcb5c530 | ||
|
|
f8d32d1d8d | ||
|
|
8c556c2849 | ||
|
|
4d0f0ceebf | ||
|
|
14abcddfcf | ||
|
|
704cc96a9f | ||
|
|
b51f610173 | ||
|
|
98050875c7 | ||
|
|
470280ea1a | ||
|
|
dafb5a8299 | ||
|
|
4a1af03744 | ||
|
|
bb176f1efb | ||
|
|
a53bcde973 | ||
|
|
1a8dc2c637 | ||
|
|
f96211ff91 | ||
|
|
77f9c02785 | ||
|
|
7910b65fdc | ||
|
|
eb4fc4588d | ||
|
|
5430674071 | ||
|
|
17e67e3b79 | ||
|
|
e87a0d72e4 | ||
|
|
67d3c65907 | ||
|
|
564a5486c9 | ||
|
|
9ce11c4c32 | ||
|
|
5e97b551a5 | ||
|
|
77536e75af | ||
|
|
3a6ab55266 | ||
|
|
aaec452bc2 |
2
.github/workflows/node.yml
vendored
2
.github/workflows/node.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: 17
|
||||
- run: npm ci
|
||||
- run: sudo apt-get install xvfb
|
||||
- name: Lint
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
lib/tsconfig.commonjs.tsbuildinfo
|
||||
tests
|
||||
perf-tests
|
||||
_spec
|
||||
*.tsbuildinfo
|
||||
*.js.map
|
||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -7,6 +7,8 @@
|
||||
"*.gql.ts": "graphql"
|
||||
},
|
||||
"eslint.options": {
|
||||
"ignorePattern": ["webpack.config.js", "scripts/*"],
|
||||
"overrideConfig": {
|
||||
"ignorePatterns": ["webpack.config.js", "scripts/*"],
|
||||
},
|
||||
}
|
||||
}
|
||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -6,11 +6,66 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v3.0.0-dev.6] - 2021-12-19
|
||||
|
||||
- Enable temporal multi-sampling by default
|
||||
- Fix flickering during marking with camera at rest
|
||||
- Enable ``aromaticBonds`` in structure representations by default
|
||||
- Add ``PluginConfig.Structure.DefaultRepresentationPreset``
|
||||
- Add ModelArchive support
|
||||
- schema extensions (e.g., AlphaFold uses it for the pLDDT score)
|
||||
- ModelArchive option in DownloadStructure action
|
||||
- ``model-archive`` GET parameter for Viewer app
|
||||
- ``Viewer.loadModelArchive`` method
|
||||
- Improve support for loading AlphaFold structures
|
||||
- Automatic coloring by pLDDT
|
||||
- AlphaFold DB option in DownloadStructure action
|
||||
- ``afdb`` GET parameter for Viewer app
|
||||
- ``Viewer.loadAlphaFoldDb`` method
|
||||
- Add QualityAssessment extension (using data from ma_qa_metric_local mmcif category)
|
||||
- pLDDT & qmean score: coloring, repr presets, molql symbol, loci labels (including avg for mutli-residue selections)
|
||||
- pLDDT: selection query
|
||||
- Warn about erroneous symmetry operator matrix (instead of throwing an error)
|
||||
- Added ``createPluginUI`` to ``mol-plugin-ui``
|
||||
- Support ``onBeforeUIRender`` to make sure initial UI works with custom presets and similar features.
|
||||
- [Breaking] Removed ``createPlugin`` and ``createPluginAsync`` from ``mol-plugin-ui``
|
||||
- Please use ``createPluginUI`` instead
|
||||
- Improve aromatic bonds handling
|
||||
- Don't detect aromatic bonds for rings < 5 atoms based on planarity
|
||||
- Prefer atoms in aromatic rings as bond reference positions
|
||||
|
||||
## [v3.0.0-dev.5] - 2021-12-16
|
||||
|
||||
- Fix initial camera reset not triggering for some entries.
|
||||
|
||||
## [v3.0.0-dev.4] - 2021-12-14
|
||||
|
||||
- Add ``bumpiness`` (per-object and per-group), ``bumpFrequency`` & ``bumpAmplitude`` (per-object) render parameters (#299)
|
||||
- Change ``label`` representation defaults: Use text border instead of rectangle background
|
||||
- Add outline color option to renderer
|
||||
- Fix false positives in Model.isFromPdbArchive
|
||||
- Add drag and drop support for loading any file, including multiple at once
|
||||
- If there are session files (.molx or .molj) among the dropped files, only the first session will be loaded
|
||||
- Add drag and drop overlay
|
||||
- Safari 15.1 - 15.3 WebGL 2 support workaround
|
||||
- [Breaking] Move ``react`` and ``react-dom`` to ``peerDependencies``. This might break some builds.
|
||||
|
||||
## [v3.0.0-dev.3] - 2021-12-4
|
||||
|
||||
- Fix OBJ and USDZ export
|
||||
|
||||
## [v3.0.0-dev.2] - 2021-12-1
|
||||
|
||||
- Do not include tests and source maps in NPM package
|
||||
|
||||
## [v3.0.0-dev.0] - 2021-11-28
|
||||
|
||||
- Add multiple lights support (with color, intensity, and direction parameters)
|
||||
- [Breaking] Add per-object material rendering properties
|
||||
- ``SimpleSettingsParams.lighting.renderStyle`` and ``RendererParams.style`` were removed
|
||||
- Add substance theme with per-group material rendering properties
|
||||
- ``StructureComponentManager.Options`` state saving support
|
||||
- ``ParamDefinition.Group.presets`` support
|
||||
|
||||
## [v2.4.1] - 2021-11-28
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -68,6 +68,17 @@ If working on just the viewer, ``npm run watch-viewer`` will provide shorter com
|
||||
|
||||
Debug/production mode in browsers can be turned on/off during runtime by calling ``setMolStarDebugMode(true/false, true/false)`` from the dev console.
|
||||
|
||||
### Cleaning and forcing a full rebuild
|
||||
npm run clean
|
||||
|
||||
Wipes the `build` and `lib` directories and `.tsbuildinfo` files.
|
||||
|
||||
npm run rebuild
|
||||
|
||||
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.
|
||||
|
||||
### Build for production:
|
||||
NODE_ENV=production npm run build
|
||||
|
||||
|
||||
@@ -246,6 +246,14 @@ citation_author.ordinal
|
||||
exptl.entry_id
|
||||
exptl.method
|
||||
|
||||
software.classification
|
||||
software.date
|
||||
software.description
|
||||
software.name
|
||||
software.pdbx_ordinal
|
||||
software.type
|
||||
software.version
|
||||
|
||||
struct.entry_id
|
||||
struct.title
|
||||
struct.pdbx_descriptor
|
||||
@@ -802,4 +810,58 @@ ihm_multi_state_modeling.population_fraction_sd
|
||||
ihm_multi_state_modeling.state_type
|
||||
ihm_multi_state_modeling.state_name
|
||||
ihm_multi_state_modeling.experiment_type
|
||||
ihm_multi_state_modeling.details
|
||||
ihm_multi_state_modeling.details
|
||||
|
||||
ma_data.content_type
|
||||
ma_data.content_type_other_details
|
||||
ma_data.id
|
||||
ma_data.name
|
||||
|
||||
ma_model_list.data_id
|
||||
ma_model_list.model_group_id
|
||||
ma_model_list.model_group_name
|
||||
ma_model_list.model_id
|
||||
ma_model_list.model_name
|
||||
ma_model_list.model_type
|
||||
ma_model_list.ordinal_id
|
||||
|
||||
ma_qa_metric.id
|
||||
ma_qa_metric.mode
|
||||
ma_qa_metric.name
|
||||
ma_qa_metric.software_group_id
|
||||
ma_qa_metric.type
|
||||
|
||||
ma_qa_metric_global.metric_id
|
||||
ma_qa_metric_global.metric_value
|
||||
ma_qa_metric_global.model_id
|
||||
ma_qa_metric_global.ordinal_id
|
||||
|
||||
ma_qa_metric_local.label_asym_id
|
||||
ma_qa_metric_local.label_comp_id
|
||||
ma_qa_metric_local.label_seq_id
|
||||
ma_qa_metric_local.metric_id
|
||||
ma_qa_metric_local.metric_value
|
||||
ma_qa_metric_local.model_id
|
||||
ma_qa_metric_local.ordinal_id
|
||||
|
||||
ma_software_group.group_id
|
||||
ma_software_group.ordinal_id
|
||||
ma_software_group.software_id
|
||||
|
||||
ma_target_entity.data_id
|
||||
ma_target_entity.entity_id
|
||||
ma_target_entity.origin
|
||||
|
||||
ma_target_entity_instance.asym_id
|
||||
ma_target_entity_instance.details
|
||||
ma_target_entity_instance.entity_id
|
||||
|
||||
ma_target_ref_db_details.db_accession
|
||||
ma_target_ref_db_details.db_code
|
||||
ma_target_ref_db_details.db_name
|
||||
ma_target_ref_db_details.ncbi_taxonomy_id
|
||||
ma_target_ref_db_details.organism_scientific
|
||||
ma_target_ref_db_details.seq_db_align_begin
|
||||
ma_target_ref_db_details.seq_db_align_end
|
||||
ma_target_ref_db_details.seq_db_isoform
|
||||
ma_target_ref_db_details.target_entity_id
|
||||
|
@@ -29,6 +29,11 @@
|
||||
* Long linear sugar chain (4HG6)
|
||||
* Anisotropic B-factors/Ellipsoids (1EJG)
|
||||
* NOS bridges (LYS-CSO in 7B0L, 6ZWJ, 6ZWH)
|
||||
* Non-polymer components in polymer entities
|
||||
* PN2 in 1F80
|
||||
* ACE (many, e.g. 5AGU, 1E1X)
|
||||
* ACY in 7ABY
|
||||
* NH2 (many, e.g. 6Y13)
|
||||
|
||||
Assembly symmetries
|
||||
* 5M30 (Assembly 1, C3 local and pseudo)
|
||||
|
||||
86
examples/ace2-hit.mol2
Normal file
86
examples/ace2-hit.mol2
Normal file
@@ -0,0 +1,86 @@
|
||||
@<TRIPOS>MOLECULE
|
||||
ace2_r_r2.top2000.poses.plain/3_Z1137565832_1_T2.pdb
|
||||
37 41 0 0 0
|
||||
SMALL
|
||||
GASTEIGER
|
||||
|
||||
@<TRIPOS>ATOM
|
||||
1 C 64.7720 85.9180 38.1090 C.3 1 LIG1 0.0799
|
||||
2 C 64.6440 84.6900 37.1570 C.3 1 LIG1 0.0306
|
||||
3 C 65.2660 83.4260 37.8080 C.3 1 LIG1 0.0927
|
||||
4 N 66.6560 83.6710 38.1790 N.pl3 1 LIG1 -0.2919
|
||||
5 C 67.7080 82.9280 37.6260 C.ar 1 LIG1 0.1520
|
||||
6 C 69.0970 83.1860 37.8250 C.ar 1 LIG1 0.0393
|
||||
7 C 70.0830 82.4100 37.1810 C.ar 1 LIG1 0.0436
|
||||
8 C 69.6450 81.3740 36.3510 C.ar 1 LIG1 0.1867
|
||||
9 N 70.3370 80.5030 35.6050 N.ar 1 LIG1 -0.1270
|
||||
10 N 69.4700 79.7480 35.0040 N.ar 1 LIG1 -0.1228
|
||||
11 C 68.2200 80.1120 35.3570 C.ar 1 LIG1 0.2583
|
||||
12 N 68.3350 81.1470 36.2040 N.ar 1 LIG1 -0.1866
|
||||
13 N 67.4230 81.8700 36.8030 N.ar 1 LIG1 -0.1473
|
||||
14 C 66.8190 84.7600 39.1350 C.3 1 LIG1 0.0927
|
||||
15 C 66.2560 86.0870 38.5570 C.3 1 LIG1 0.0306
|
||||
16 N 64.4520 87.4670 36.2150 N.am 1 LIG1 -0.2979
|
||||
17 H 64.9740 86.7650 35.7110 H 1 LIG1 0.1498
|
||||
18 C 64.2290 87.1720 37.5220 C.2 1 LIG1 0.2224
|
||||
19 O 63.5690 87.9550 38.2480 O.2 1 LIG1 -0.2751
|
||||
20 C 64.0160 88.6470 35.5420 C.3 1 LIG1 0.1559
|
||||
21 C 65.9650 88.2170 32.5700 C.ar 1 LIG1 0.1629
|
||||
22 N 65.8040 88.0390 33.8860 N.ar 1 LIG1 -0.3232
|
||||
23 H 66.4190 87.5270 34.5040 H 1 LIG1 0.1686
|
||||
24 C 64.6770 88.6690 34.2330 C.ar 1 LIG1 0.1601
|
||||
25 N 64.1890 89.2810 33.1430 N.ar 1 LIG1 -0.1318
|
||||
26 N 64.9640 89.0070 32.1450 N.ar 1 LIG1 -0.1293
|
||||
27 F 69.9260 86.0280 29.3520 F 1 LIG1 -0.2042
|
||||
28 C 68.9880 86.5420 30.0990 C.ar 1 LIG1 0.1401
|
||||
29 C 67.6590 86.0900 29.9830 C.ar 1 LIG1 0.0297
|
||||
30 C 66.6500 86.6450 30.7950 C.ar 1 LIG1 0.0053
|
||||
31 C 66.9590 87.6470 31.7450 C.ar 1 LIG1 0.0359
|
||||
32 C 68.2970 88.0990 31.8400 C.ar 1 LIG1 0.0053
|
||||
33 C 69.3030 87.5560 31.0230 C.ar 1 LIG1 0.0297
|
||||
34 C 66.9850 79.4910 34.8440 C.3 1 LIG1 0.4541
|
||||
35 F 67.3150 78.4110 34.0640 F 1 LIG1 -0.1631
|
||||
36 F 66.2460 80.3690 34.0910 F 1 LIG1 -0.1631
|
||||
37 F 66.1920 79.0650 35.8800 F 1 LIG1 -0.1631
|
||||
@<TRIPOS>BOND
|
||||
1 1 2 1
|
||||
2 1 18 1
|
||||
3 1 15 1
|
||||
4 2 3 1
|
||||
5 3 4 1
|
||||
6 4 5 1
|
||||
7 4 14 1
|
||||
8 5 13 ar
|
||||
9 5 6 ar
|
||||
10 6 7 ar
|
||||
11 7 8 ar
|
||||
12 8 9 ar
|
||||
13 8 12 ar
|
||||
14 9 10 ar
|
||||
15 10 11 ar
|
||||
16 11 34 1
|
||||
17 11 12 ar
|
||||
18 12 13 ar
|
||||
19 14 15 1
|
||||
20 16 20 1
|
||||
21 16 17 1
|
||||
22 16 18 am
|
||||
23 18 19 2
|
||||
24 20 24 1
|
||||
25 21 31 1
|
||||
26 21 26 ar
|
||||
27 21 22 ar
|
||||
28 22 24 ar
|
||||
29 22 23 1
|
||||
30 24 25 ar
|
||||
31 25 26 ar
|
||||
32 27 28 1
|
||||
33 28 29 ar
|
||||
34 28 33 ar
|
||||
35 29 30 ar
|
||||
36 30 31 ar
|
||||
37 31 32 ar
|
||||
38 32 33 ar
|
||||
39 34 35 1
|
||||
40 34 36 1
|
||||
41 34 37 1
|
||||
7628
examples/ace2.pdbqt
Normal file
7628
examples/ace2.pdbqt
Normal file
File diff suppressed because it is too large
Load Diff
168
package-lock.json
generated
168
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.0.0-dev.0",
|
||||
"version": "3.0.0-dev.6",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "molstar",
|
||||
"version": "3.0.0-dev.0",
|
||||
"version": "3.0.0-dev.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/argparse": "^2.0.10",
|
||||
@@ -27,8 +27,6 @@
|
||||
"immer": "^9.0.7",
|
||||
"immutable": "^3.8.2",
|
||||
"node-fetch": "^2.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"rxjs": "^7.4.0",
|
||||
"swagger-ui-dist": "^4.1.1",
|
||||
"tslib": "^2.3.1",
|
||||
@@ -56,8 +54,8 @@
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/gl": "^4.1.0",
|
||||
"@types/jest": "^27.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.5.0",
|
||||
"@typescript-eslint/parser": "^5.5.0",
|
||||
"benchmark": "^2.1.4",
|
||||
"concurrently": "^6.4.0",
|
||||
"cpx2": "^4.0.0",
|
||||
@@ -85,6 +83,10 @@
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"gl": "^4.9.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -2885,13 +2887,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.4.0.tgz",
|
||||
"integrity": "sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz",
|
||||
"integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/experimental-utils": "5.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.4.0",
|
||||
"@typescript-eslint/experimental-utils": "5.5.0",
|
||||
"@typescript-eslint/scope-manager": "5.5.0",
|
||||
"debug": "^4.3.2",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"ignore": "^5.1.8",
|
||||
@@ -2917,15 +2919,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.4.0.tgz",
|
||||
"integrity": "sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz",
|
||||
"integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@typescript-eslint/scope-manager": "5.4.0",
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/typescript-estree": "5.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.5.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/typescript-estree": "5.5.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
@@ -2941,14 +2943,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.4.0.tgz",
|
||||
"integrity": "sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz",
|
||||
"integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "5.4.0",
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/typescript-estree": "5.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.5.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/typescript-estree": "5.5.0",
|
||||
"debug": "^4.3.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2968,13 +2970,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.4.0.tgz",
|
||||
"integrity": "sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz",
|
||||
"integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/visitor-keys": "5.4.0"
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/visitor-keys": "5.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
@@ -2985,9 +2987,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.4.0.tgz",
|
||||
"integrity": "sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz",
|
||||
"integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
@@ -2998,13 +3000,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz",
|
||||
"integrity": "sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz",
|
||||
"integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/visitor-keys": "5.4.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/visitor-keys": "5.5.0",
|
||||
"debug": "^4.3.2",
|
||||
"globby": "^11.0.4",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -3025,12 +3027,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz",
|
||||
"integrity": "sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz",
|
||||
"integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"eslint-visitor-keys": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -11292,6 +11294,7 @@
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
@@ -11304,6 +11307,7 @@
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -11864,6 +11868,7 @@
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
@@ -12522,9 +12527,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-ui-dist": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.1.1.tgz",
|
||||
"integrity": "sha512-xvPMEpOCbd5S9Z1pJT/L/K/C2yAX89ZWJDxEECkVW1dENsKFLbu7sRY7b6UBqLXuTUfdM5owlgPrpwr24CRonA=="
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.1.3.tgz",
|
||||
"integrity": "sha512-WvfPSfAAMlE/sKS6YkW47nX/hA7StmhYnAHc6wWCXNL0oclwLj6UXv0hQCkLnDgvebi0MEV40SJJpVjKUgH1IQ=="
|
||||
},
|
||||
"node_modules/swap-case": {
|
||||
"version": "2.0.2",
|
||||
@@ -16064,13 +16069,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.4.0.tgz",
|
||||
"integrity": "sha512-9/yPSBlwzsetCsGEn9j24D8vGQgJkOTr4oMLas/w886ZtzKIs1iyoqFrwsX2fqYEeUwsdBpC21gcjRGo57u0eg==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz",
|
||||
"integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "5.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.4.0",
|
||||
"@typescript-eslint/experimental-utils": "5.5.0",
|
||||
"@typescript-eslint/scope-manager": "5.5.0",
|
||||
"debug": "^4.3.2",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"ignore": "^5.1.8",
|
||||
@@ -16080,55 +16085,55 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.4.0.tgz",
|
||||
"integrity": "sha512-Nz2JDIQUdmIGd6p33A+naQmwfkU5KVTLb/5lTk+tLVTDacZKoGQisj8UCxk7onJcrgjIvr8xWqkYI+DbI3TfXg==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz",
|
||||
"integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@typescript-eslint/scope-manager": "5.4.0",
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/typescript-estree": "5.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.5.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/typescript-estree": "5.5.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.4.0.tgz",
|
||||
"integrity": "sha512-JoB41EmxiYpaEsRwpZEYAJ9XQURPFer8hpkIW9GiaspVLX8oqbqNM8P4EP8HOZg96yaALiLEVWllA2E8vwsIKw==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz",
|
||||
"integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/scope-manager": "5.4.0",
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/typescript-estree": "5.4.0",
|
||||
"@typescript-eslint/scope-manager": "5.5.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/typescript-estree": "5.5.0",
|
||||
"debug": "^4.3.2"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.4.0.tgz",
|
||||
"integrity": "sha512-pRxFjYwoi8R+n+sibjgF9iUiAELU9ihPBtHzocyW8v8D8G8KeQvXTsW7+CBYIyTYsmhtNk50QPGLE3vrvhM5KA==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz",
|
||||
"integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/visitor-keys": "5.4.0"
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/visitor-keys": "5.5.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.4.0.tgz",
|
||||
"integrity": "sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz",
|
||||
"integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz",
|
||||
"integrity": "sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz",
|
||||
"integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/visitor-keys": "5.4.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"@typescript-eslint/visitor-keys": "5.5.0",
|
||||
"debug": "^4.3.2",
|
||||
"globby": "^11.0.4",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -16137,12 +16142,12 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz",
|
||||
"integrity": "sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz",
|
||||
"integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "5.4.0",
|
||||
"@typescript-eslint/types": "5.5.0",
|
||||
"eslint-visitor-keys": "^3.0.0"
|
||||
}
|
||||
},
|
||||
@@ -22606,6 +22611,7 @@
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
@@ -22615,6 +22621,7 @@
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
|
||||
"integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -23039,6 +23046,7 @@
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
|
||||
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
@@ -23553,9 +23561,9 @@
|
||||
}
|
||||
},
|
||||
"swagger-ui-dist": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.1.1.tgz",
|
||||
"integrity": "sha512-xvPMEpOCbd5S9Z1pJT/L/K/C2yAX89ZWJDxEECkVW1dENsKFLbu7sRY7b6UBqLXuTUfdM5owlgPrpwr24CRonA=="
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.1.3.tgz",
|
||||
"integrity": "sha512-WvfPSfAAMlE/sKS6YkW47nX/hA7StmhYnAHc6wWCXNL0oclwLj6UXv0hQCkLnDgvebi0MEV40SJJpVjKUgH1IQ=="
|
||||
},
|
||||
"swap-case": {
|
||||
"version": "2.0.2",
|
||||
|
||||
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.0.0-dev.0",
|
||||
"version": "3.0.0-dev.6",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
@@ -16,6 +16,8 @@
|
||||
"test": "npm run lint && jest",
|
||||
"jest": "jest",
|
||||
"build": "npm run build-tsc && npm run build-extra && npm run build-webpack",
|
||||
"clean": "node ./scripts/clean.js",
|
||||
"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}\" lib/",
|
||||
@@ -36,7 +38,7 @@
|
||||
"volume-server-test": "node lib/commonjs/servers/volume/server.js --idMap em 'test/${id}.mdb' --defaultPort 1336",
|
||||
"plugin-state": "node lib/commonjs/servers/plugin-state/index.js --working-folder ./build/state --port 1339",
|
||||
"preversion": "npm run test",
|
||||
"version": "npm run build",
|
||||
"version": "npm run rebuild && cpx .npmignore lib/",
|
||||
"postversion": "git push && git push --tags"
|
||||
},
|
||||
"files": [
|
||||
@@ -98,8 +100,8 @@
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/gl": "^4.1.0",
|
||||
"@types/jest": "^27.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.5.0",
|
||||
"@typescript-eslint/parser": "^5.5.0",
|
||||
"benchmark": "^2.1.4",
|
||||
"concurrently": "^6.4.0",
|
||||
"cpx2": "^4.0.0",
|
||||
@@ -144,14 +146,16 @@
|
||||
"immer": "^9.0.7",
|
||||
"immutable": "^3.8.2",
|
||||
"node-fetch": "^2.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"rxjs": "^7.4.0",
|
||||
"swagger-ui-dist": "^4.1.1",
|
||||
"tslib": "^2.3.1",
|
||||
"util.promisify": "^1.1.1",
|
||||
"xhr2": "^0.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"gl": "^4.9.2"
|
||||
}
|
||||
|
||||
41
scripts/clean.js
Normal file
41
scripts/clean.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Michal Malý <malym@ibt.cas.cz>
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function removeDir(dirPath) {
|
||||
for (const ent of fs.readdirSync(dirPath)) {
|
||||
const entryPath = path.join(dirPath, ent);
|
||||
remove(entryPath);
|
||||
}
|
||||
|
||||
fs.rmdirSync(dirPath);
|
||||
}
|
||||
|
||||
function remove(entryPath) {
|
||||
const st = fs.statSync(entryPath);
|
||||
if (st.isDirectory())
|
||||
removeDir(entryPath);
|
||||
else
|
||||
fs.unlinkSync(entryPath);
|
||||
}
|
||||
|
||||
const toClean = [
|
||||
path.resolve(__dirname, '../build'),
|
||||
path.resolve(__dirname, '../lib'),
|
||||
path.resolve(__dirname, '../tsconfig.tsbuildinfo'),
|
||||
];
|
||||
|
||||
toClean.forEach(ph => {
|
||||
if (fs.existsSync(ph)) {
|
||||
try {
|
||||
remove(ph);
|
||||
} catch (err) {
|
||||
console.warn(`Cleanup failed: ${err}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -14,6 +14,9 @@ const buildDir = path.resolve(__dirname, '../build/');
|
||||
const deployDir = path.resolve(buildDir, 'deploy/');
|
||||
const localPath = 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 -->`;
|
||||
|
||||
function log(command, stdout, stderr) {
|
||||
if (command) {
|
||||
console.log('\n###', command);
|
||||
@@ -22,11 +25,36 @@ function log(command, stdout, stderr) {
|
||||
}
|
||||
}
|
||||
|
||||
function addAnalytics(path) {
|
||||
const data = fs.readFileSync(path, 'utf8');
|
||||
const result = data.replace(analyticsTag, analyticsCode);
|
||||
fs.writeFileSync(path, result, 'utf8');
|
||||
}
|
||||
|
||||
function copyViewer() {
|
||||
console.log('\n###', 'copy viewer files');
|
||||
const viewerBuildPath = path.resolve(buildDir, '../build/viewer/');
|
||||
const viewerDeployPath = path.resolve(localPath, 'viewer/');
|
||||
fse.copySync(viewerBuildPath, viewerDeployPath, { overwrite: true });
|
||||
addAnalytics(path.resolve(viewerDeployPath, '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'));
|
||||
}
|
||||
|
||||
function copyFiles() {
|
||||
copyViewer();
|
||||
copyDemos();
|
||||
}
|
||||
|
||||
if (!fs.existsSync(localPath)) {
|
||||
@@ -42,9 +70,9 @@ if (!fs.existsSync(path.resolve(localPath, '.git/'))) {
|
||||
.outputHandler(log)
|
||||
.clone(remoteUrl, localPath)
|
||||
.fetch(['--all'])
|
||||
.exec(copyViewer)
|
||||
.exec(copyFiles)
|
||||
.add(['-A'])
|
||||
.commit('updated viewer')
|
||||
.commit('updated viewer & demos')
|
||||
.push();
|
||||
} else {
|
||||
console.log('\n###', 'update repository');
|
||||
@@ -52,8 +80,8 @@ if (!fs.existsSync(path.resolve(localPath, '.git/'))) {
|
||||
.outputHandler(log)
|
||||
.fetch(['--all'])
|
||||
.reset(['--hard', 'origin/master'])
|
||||
.exec(copyViewer)
|
||||
.exec(copyFiles)
|
||||
.add(['-A'])
|
||||
.commit('updated viewer')
|
||||
.commit('updated viewer & demos')
|
||||
.push();
|
||||
}
|
||||
@@ -19,19 +19,19 @@
|
||||
<div id="app"></div>
|
||||
<script type="text/javascript" src="./molstar.js"></script>
|
||||
<script type="text/javascript">
|
||||
var viewer = new DockingViewer('app', [0x33DD22, 0x1133EE], true);
|
||||
|
||||
function getParam(name, regex) {
|
||||
var r = new RegExp(name + '=' + '(' + regex + ')[&]?', 'i');
|
||||
return decodeURIComponent(((window.location.search || '').match(r) || [])[1] || '');
|
||||
}
|
||||
var pdbqt = getParam('pdbqt', '[^&]+').trim();
|
||||
var mol2 = getParam('mol2', '[^&]+').trim();
|
||||
var pdbqt = getParam('pdbqt', '[^&]+').trim() || '../../examples/ace2.pdbqt';
|
||||
var mol2 = getParam('mol2', '[^&]+').trim() || '../../examples/ace2-hit.mol2';
|
||||
|
||||
viewer.loadStructuresFromUrlsAndMerge([
|
||||
{ url: pdbqt, format: 'pdbqt' },
|
||||
{ url: mol2, format: 'mol2' }
|
||||
]);
|
||||
DockingViewer.create('app', [0x33DD22, 0x1133EE], true).then(viewer => {
|
||||
viewer.loadStructuresFromUrlsAndMerge([
|
||||
{ url: pdbqt, format: 'pdbqt' },
|
||||
{ url: mol2, format: 'mol2' }
|
||||
]);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,7 +8,7 @@
|
||||
import { Structure } from '../../mol-model/structure';
|
||||
import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
|
||||
import { PluginStateObject as PSO, PluginStateTransform } from '../../mol-plugin-state/objects';
|
||||
import { createPlugin } from '../../mol-plugin-ui';
|
||||
import { createPluginUI } from '../../mol-plugin-ui';
|
||||
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
||||
import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
|
||||
import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
|
||||
@@ -54,9 +54,10 @@ const DefaultViewerOptions = {
|
||||
};
|
||||
|
||||
class Viewer {
|
||||
plugin: PluginUIContext
|
||||
constructor(public plugin: PluginUIContext) {
|
||||
}
|
||||
|
||||
constructor(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) {
|
||||
static async create(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) {
|
||||
const o = { ...DefaultViewerOptions, ...{
|
||||
layoutIsExpanded: false,
|
||||
layoutShowControls: false,
|
||||
@@ -125,29 +126,31 @@ class Viewer {
|
||||
? document.getElementById(elementOrId)
|
||||
: elementOrId;
|
||||
if (!element) throw new Error(`Could not get element with id '${elementOrId}'`);
|
||||
this.plugin = createPlugin(element, spec);
|
||||
const plugin = await createPluginUI(element, spec);
|
||||
|
||||
(this.plugin.customState as any) = {
|
||||
(plugin.customState as any) = {
|
||||
colorPalette: {
|
||||
name: 'colors',
|
||||
params: { list: { colors } }
|
||||
}
|
||||
};
|
||||
|
||||
this.plugin.behaviors.canvas3d.initialized.subscribe(v => {
|
||||
plugin.behaviors.canvas3d.initialized.subscribe(v => {
|
||||
if (v) {
|
||||
PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: {
|
||||
PluginCommands.Canvas3D.SetSettings(plugin, { settings: {
|
||||
renderer: {
|
||||
...this.plugin.canvas3d!.props.renderer,
|
||||
...plugin.canvas3d!.props.renderer,
|
||||
backgroundColor: ColorNames.white,
|
||||
},
|
||||
camera: {
|
||||
...this.plugin.canvas3d!.props.camera,
|
||||
...plugin.canvas3d!.props.camera,
|
||||
helper: { axes: { name: 'off', params: {} } }
|
||||
}
|
||||
} });
|
||||
}
|
||||
});
|
||||
|
||||
return new Viewer(plugin);
|
||||
}
|
||||
|
||||
async loadStructuresFromUrlsAndMerge(sources: { url: string, format: BuiltInTrajectoryFormat, isBinary?: boolean }[]) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import { PluginContext } from '../../mol-plugin/context';
|
||||
import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
|
||||
import { StateObjectRef } from '../../mol-state';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import { Material } from '../../mol-util/material';
|
||||
|
||||
function shinyStyle(plugin: PluginContext) {
|
||||
return PluginCommands.Canvas3D.SetSettings(plugin, { settings: {
|
||||
@@ -50,7 +51,8 @@ function occlusionStyle(plugin: PluginContext) {
|
||||
} },
|
||||
outline: { name: 'on', params: {
|
||||
scale: 1.0,
|
||||
threshold: 0.33
|
||||
threshold: 0.33,
|
||||
color: Color(0x0000),
|
||||
} }
|
||||
}
|
||||
} });
|
||||
@@ -75,7 +77,7 @@ const PresetParams = {
|
||||
...StructureRepresentationPresetProvider.CommonParams,
|
||||
};
|
||||
|
||||
|
||||
const CustomMaterial = Material({ roughness: 0.2, metalness: 0 });
|
||||
|
||||
export const StructurePreset = StructureRepresentationPresetProvider({
|
||||
id: 'preset-structure',
|
||||
@@ -92,8 +94,8 @@ export const StructurePreset = StructureRepresentationPresetProvider({
|
||||
|
||||
const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
|
||||
const representations = {
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, roughness: 0.2, sizeFactor: 0.35 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, roughness: 0.2 }, color: 'chain-id', colorParams: { palette: (plugin.customState as any).colorPalette } }, { tag: 'polymer' }),
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.35 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
polymer: builder.buildRepresentation(update, components.polymer, { type: 'cartoon', typeParams: { ...typeParams, material: CustomMaterial }, color: 'chain-id', colorParams: { palette: (plugin.customState as any).colorPalette } }, { tag: 'polymer' }),
|
||||
};
|
||||
|
||||
await update.commit({ revertOnError: true });
|
||||
@@ -147,8 +149,8 @@ const SurfacePreset = StructureRepresentationPresetProvider({
|
||||
|
||||
const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
|
||||
const representations = {
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, roughness: 0.2, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
polymer: builder.buildRepresentation(update, components.polymer, { type: 'molecular-surface', typeParams: { ...typeParams, roughness: 0.2, quality: 'custom', resolution: 0.5, doubleSided: true }, color: 'partial-charge' }, { tag: 'polymer' }),
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
polymer: builder.buildRepresentation(update, components.polymer, { type: 'molecular-surface', typeParams: { ...typeParams, material: CustomMaterial, quality: 'custom', resolution: 0.5, doubleSided: true }, color: 'partial-charge' }, { tag: 'polymer' }),
|
||||
};
|
||||
|
||||
await update.commit({ revertOnError: true });
|
||||
@@ -175,8 +177,8 @@ const PocketPreset = StructureRepresentationPresetProvider({
|
||||
|
||||
const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
|
||||
const representations = {
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, roughness: 0.2, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
surroundings: builder.buildRepresentation(update, components.surroundings, { type: 'molecular-surface', typeParams: { ...typeParams, roughness: 0.2, includeParent: true, quality: 'custom', resolution: 0.2, doubleSided: true }, color: 'partial-charge' }, { tag: 'surroundings' }),
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.26 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
surroundings: builder.buildRepresentation(update, components.surroundings, { type: 'molecular-surface', typeParams: { ...typeParams, material: CustomMaterial, includeParent: true, quality: 'custom', resolution: 0.2, doubleSided: true }, color: 'partial-charge' }, { tag: 'surroundings' }),
|
||||
};
|
||||
|
||||
await update.commit({ revertOnError: true });
|
||||
@@ -204,10 +206,10 @@ const InteractionsPreset = StructureRepresentationPresetProvider({
|
||||
|
||||
const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
|
||||
const representations = {
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, roughness: 0.2, sizeFactor: 0.3 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
ballAndStick: builder.buildRepresentation(update, components.surroundings, { type: 'ball-and-stick', typeParams: { ...typeParams, roughness: 0.2, sizeFactor: 0.1, sizeAspectRatio: 1 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ball-and-stick' }),
|
||||
interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams, roughness: 0.2 }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
|
||||
label: builder.buildRepresentation(update, components.surroundings, { type: 'label', typeParams: { ...typeParams, roughness: 0.2, background: false, borderWidth: 0.1 }, color: 'uniform', colorParams: { value: Color(0x000000) } }, { tag: 'label' }),
|
||||
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.3 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
|
||||
ballAndStick: builder.buildRepresentation(update, components.surroundings, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.1, sizeAspectRatio: 1 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ball-and-stick' }),
|
||||
interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams, material: CustomMaterial }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
|
||||
label: builder.buildRepresentation(update, components.surroundings, { type: 'label', typeParams: { ...typeParams, material: CustomMaterial, background: false, borderWidth: 0.1 }, color: 'uniform', colorParams: { value: Color(0x000000) } }, { tag: 'label' }),
|
||||
};
|
||||
|
||||
await update.commit({ revertOnError: true });
|
||||
@@ -228,7 +230,7 @@ export class ViewportComponent extends PluginUIComponent {
|
||||
|
||||
set = async (preset: StructureRepresentationPresetProvider) => {
|
||||
await this._set(this.plugin.managers.structure.hierarchy.selection.structures, preset);
|
||||
}
|
||||
};
|
||||
|
||||
structurePreset = () => this.set(StructurePreset);
|
||||
illustrativePreset = () => this.set(IllustrativePreset);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div id="app"></div>
|
||||
<script type="text/javascript" src="./molstar.js"></script>
|
||||
<script type="text/javascript">
|
||||
var viewer = new molstar.Viewer('app', {
|
||||
molstar.Viewer.create('app', {
|
||||
layoutIsExpanded: true,
|
||||
layoutShowControls: false,
|
||||
layoutShowRemoteState: false,
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
pdbProvider: 'rcsb',
|
||||
emdbProvider: 'rcsb',
|
||||
}).then(viewer => {
|
||||
viewer.loadPdb('7bv2');
|
||||
viewer.loadEmdb('EMD-30210', { detail: 6 });
|
||||
// viewer.loadAllModelsOrAssemblyFromUrl('https://cs.litemol.org/5ire/full', 'mmcif', false, { representationParams: { theme: { globalName: 'operator-name' } } })
|
||||
});
|
||||
viewer.loadPdb('7bv2');
|
||||
viewer.loadEmdb('EMD-30210', { detail: 6 });
|
||||
|
||||
// viewer.loadAllModelsOrAssemblyFromUrl('https://cs.litemol.org/5ire/full', 'mmcif', false, { representationParams: { theme: { globalName: 'operator-name' } } })
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -56,7 +56,8 @@
|
||||
var pixelScale = getParam('pixel-scale', '[^&]+').trim();
|
||||
var pickScale = getParam('pick-scale', '[^&]+').trim();
|
||||
var pickPadding = getParam('pick-padding', '[^&]+').trim();
|
||||
var viewer = new molstar.Viewer('app', {
|
||||
|
||||
molstar.Viewer.create('app', {
|
||||
layoutShowControls: !hideControls,
|
||||
viewportShowExpand: false,
|
||||
collapseLeftPanel: collapseLeftPanel,
|
||||
@@ -68,28 +69,35 @@
|
||||
pixelScale: parseFloat(pixelScale) || 1,
|
||||
pickScale: parseFloat(pickScale) || 0.25,
|
||||
pickPadding: isNaN(parseFloat(pickPadding)) ? 1 : parseFloat(pickPadding),
|
||||
}).then(viewer => {
|
||||
var snapshotId = getParam('snapshot-id', '[^&]+').trim();
|
||||
if (snapshotId) viewer.setRemoteSnapshot(snapshotId);
|
||||
|
||||
var snapshotUrl = getParam('snapshot-url', '[^&]+').trim();
|
||||
var snapshotUrlType = getParam('snapshot-url-type', '[^&]+').toLowerCase().trim() || 'molj';
|
||||
if (snapshotUrl && snapshotUrlType) viewer.loadSnapshotFromUrl(snapshotUrl, snapshotUrlType);
|
||||
|
||||
var structureUrl = getParam('structure-url', '[^&]+').trim();
|
||||
var structureUrlFormat = getParam('structure-url-format', '[a-z]+').toLowerCase().trim();
|
||||
var structureUrlIsBinary = getParam('structure-url-is-binary', '[^&]+').trim() === '1';
|
||||
if (structureUrl) viewer.loadStructureFromUrl(structureUrl, structureUrlFormat, structureUrlIsBinary);
|
||||
|
||||
var pdb = getParam('pdb', '[^&]+').trim();
|
||||
if (pdb) viewer.loadPdb(pdb);
|
||||
|
||||
var pdbDev = getParam('pdb-dev', '[^&]+').trim();
|
||||
if (pdbDev) viewer.loadPdbDev(pdbDev);
|
||||
|
||||
var emdb = getParam('emdb', '[^&]+').trim();
|
||||
if (emdb) viewer.loadEmdb(emdb);
|
||||
|
||||
var afdb = getParam('afdb', '[^&]+').trim();
|
||||
if (afdb) viewer.loadAlphaFoldDb(afdb);
|
||||
|
||||
var modelArchive = getParam('model-archive', '[^&]+').trim();
|
||||
if (modelArchive) viewer.loadModelArchive(modelArchive);
|
||||
});
|
||||
|
||||
var snapshotId = getParam('snapshot-id', '[^&]+').trim();
|
||||
if (snapshotId) viewer.setRemoteSnapshot(snapshotId);
|
||||
|
||||
var snapshotUrl = getParam('snapshot-url', '[^&]+').trim();
|
||||
var snapshotUrlType = getParam('snapshot-url-type', '[^&]+').toLowerCase().trim() || 'molj';
|
||||
if (snapshotUrl && snapshotUrlType) viewer.loadSnapshotFromUrl(snapshotUrl, snapshotUrlType);
|
||||
|
||||
var structureUrl = getParam('structure-url', '[^&]+').trim();
|
||||
var structureUrlFormat = getParam('structure-url-format', '[a-z]+').toLowerCase().trim();
|
||||
var structureUrlIsBinary = getParam('structure-url-is-binary', '[^&]+').trim() === '1';
|
||||
if (structureUrl) viewer.loadStructureFromUrl(structureUrl, structureUrlFormat, structureUrlIsBinary);
|
||||
|
||||
var pdb = getParam('pdb', '[^&]+').trim();
|
||||
if (pdb) viewer.loadPdb(pdb);
|
||||
|
||||
var pdbDev = getParam('pdb-dev', '[^&]+').trim();
|
||||
if (pdbDev) viewer.loadPdbDev(pdbDev);
|
||||
|
||||
var emdb = getParam('emdb', '[^&]+').trim();
|
||||
if (emdb) viewer.loadEmdb(emdb);
|
||||
</script>
|
||||
<!-- __MOLSTAR_ANALYTICS__ -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -10,13 +10,16 @@ import { CellPack } from '../../extensions/cellpack';
|
||||
import { DnatcoConfalPyramids } from '../../extensions/dnatco';
|
||||
import { G3DFormat, G3dProvider } from '../../extensions/g3d/format';
|
||||
import { GeometryExport } from '../../extensions/geo-export';
|
||||
import { MAQualityAssessment } from '../../extensions/model-archive/quality-assessment/behavior';
|
||||
import { QualityAssessmentPLDDTPreset, QualityAssessmentQmeanPreset } from '../../extensions/model-archive/quality-assessment/behavior';
|
||||
import { QualityAssessment } from '../../extensions/model-archive/quality-assessment/prop';
|
||||
import { Mp4Export } from '../../extensions/mp4-export';
|
||||
import { PDBeStructureQualityReport } from '../../extensions/pdbe';
|
||||
import { RCSBAssemblySymmetry, RCSBValidationReport } from '../../extensions/rcsb';
|
||||
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 { StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
|
||||
import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from '../../mol-plugin-state/builder/structure/representation-preset';
|
||||
import { DataFormatProvider } from '../../mol-plugin-state/formats/provider';
|
||||
import { BuildInStructureFormat } from '../../mol-plugin-state/formats/structure';
|
||||
import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
|
||||
@@ -25,7 +28,7 @@ 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 { createPlugin } from '../../mol-plugin-ui';
|
||||
import { createPluginUI } from '../../mol-plugin-ui';
|
||||
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
||||
import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
@@ -33,7 +36,7 @@ import { PluginConfig } from '../../mol-plugin/config';
|
||||
import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
|
||||
import { PluginSpec } from '../../mol-plugin/spec';
|
||||
import { PluginState } from '../../mol-plugin/state';
|
||||
import { StateObjectSelector } from '../../mol-state';
|
||||
import { StateObjectRef, StateObjectSelector } from '../../mol-state';
|
||||
import { Asset } from '../../mol-util/assets';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import '../../mol-util/polyfill';
|
||||
@@ -60,7 +63,8 @@ const Extensions = {
|
||||
'anvil-membrane-orientation': PluginSpec.Behavior(ANVILMembraneOrientation),
|
||||
'g3d': PluginSpec.Behavior(G3DFormat),
|
||||
'mp4-export': PluginSpec.Behavior(Mp4Export),
|
||||
'geo-export': PluginSpec.Behavior(GeometryExport)
|
||||
'geo-export': PluginSpec.Behavior(GeometryExport),
|
||||
'ma-quality-assessment': PluginSpec.Behavior(MAQualityAssessment),
|
||||
};
|
||||
|
||||
const DefaultViewerOptions = {
|
||||
@@ -95,9 +99,10 @@ const DefaultViewerOptions = {
|
||||
type ViewerOptions = typeof DefaultViewerOptions;
|
||||
|
||||
export class Viewer {
|
||||
plugin: PluginUIContext
|
||||
constructor(public plugin: PluginUIContext) {
|
||||
}
|
||||
|
||||
constructor(elementOrId: string | HTMLElement, options: Partial<ViewerOptions> = {}) {
|
||||
static async create(elementOrId: string | HTMLElement, options: Partial<ViewerOptions> = {}) {
|
||||
const o = { ...DefaultViewerOptions, ...options };
|
||||
const defaultSpec = DefaultPluginUISpec();
|
||||
|
||||
@@ -149,7 +154,8 @@ export class Viewer {
|
||||
[PluginConfig.VolumeStreaming.DefaultServer, o.volumeStreamingServer],
|
||||
[PluginConfig.VolumeStreaming.Enabled, !o.volumeStreamingDisabled],
|
||||
[PluginConfig.Download.DefaultPdbProvider, o.pdbProvider],
|
||||
[PluginConfig.Download.DefaultEmdbProvider, o.emdbProvider]
|
||||
[PluginConfig.Download.DefaultEmdbProvider, o.emdbProvider],
|
||||
[PluginConfig.Structure.DefaultRepresentationPreset, ViewerAutoPreset.id],
|
||||
]
|
||||
};
|
||||
|
||||
@@ -157,7 +163,14 @@ export class Viewer {
|
||||
? document.getElementById(elementOrId)
|
||||
: elementOrId;
|
||||
if (!element) throw new Error(`Could not get element with id '${elementOrId}'`);
|
||||
this.plugin = createPlugin(element, spec);
|
||||
const plugin = await createPluginUI(element, spec, {
|
||||
onBeforeUIRender: plugin => {
|
||||
// the preset needs to be added before the UI renders otherwise
|
||||
// "Download Structure" wont be able to pick it up
|
||||
plugin.builders.structure.representation.registerPreset(ViewerAutoPreset);
|
||||
}
|
||||
});
|
||||
return new Viewer(plugin);
|
||||
}
|
||||
|
||||
setRemoteSnapshot(id: string) {
|
||||
@@ -251,6 +264,35 @@ export class Viewer {
|
||||
}));
|
||||
}
|
||||
|
||||
loadAlphaFoldDb(afdb: 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: 'alphafolddb' as const,
|
||||
params: {
|
||||
id: afdb,
|
||||
options: {
|
||||
...params.source.params.options,
|
||||
representation: 'preset-structure-representation-ma-quality-assessment-plddt'
|
||||
},
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
loadModelArchive(id: 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: 'modelarchive' as const,
|
||||
params: {
|
||||
id,
|
||||
options: params.source.params.options,
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* @example Load X-ray density from volume server
|
||||
viewer.loadVolumeFromUrl({
|
||||
@@ -409,4 +451,32 @@ export interface LoadTrajectoryParams {
|
||||
| { kind: 'coordinates-data', data: string | number[] | ArrayBuffer | Uint8Array, format: BuildInStructureFormat },
|
||||
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 {
|
||||
return await PresetStructureRepresentations.auto.apply(ref, params, plugin);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -35,20 +35,16 @@ async function runGenerateSchemaMmcif(name: string, fieldNamesPath: string, type
|
||||
const ihmDic = await parseCifText(fs.readFileSync(IHM_DIC_PATH, 'utf8')).run();
|
||||
if (ihmDic.isError) throw ihmDic;
|
||||
|
||||
await ensureCarbBranchDicAvailable();
|
||||
const carbBranchDic = await parseCifText(fs.readFileSync(CARB_BRANCH_DIC_PATH, 'utf8')).run();
|
||||
if (carbBranchDic.isError) throw carbBranchDic;
|
||||
|
||||
await ensureCarbCompDicAvailable();
|
||||
const carbCompDic = await parseCifText(fs.readFileSync(CARB_COMP_DIC_PATH, 'utf8')).run();
|
||||
if (carbCompDic.isError) throw carbCompDic;
|
||||
await ensureMaDicAvailable();
|
||||
const maDic = await parseCifText(fs.readFileSync(MA_DIC_PATH, 'utf8')).run();
|
||||
if (maDic.isError) throw maDic;
|
||||
|
||||
const mmcifDicVersion = getDicVersion(mmcifDic.result.blocks[0]);
|
||||
const ihmDicVersion = getDicVersion(ihmDic.result.blocks[0]);
|
||||
const carbDicVersion = 'draft';
|
||||
const version = `Dictionary versions: mmCIF ${mmcifDicVersion}, IHM ${ihmDicVersion}, CARB ${carbDicVersion}.`;
|
||||
const maDicVersion = getDicVersion(maDic.result.blocks[0]);
|
||||
const version = `Dictionary versions: mmCIF ${mmcifDicVersion}, IHM ${ihmDicVersion}, MA ${maDicVersion}.`;
|
||||
|
||||
const frames: CifFrame[] = [...mmcifDic.result.blocks[0].saveFrames, ...ihmDic.result.blocks[0].saveFrames, ...carbBranchDic.result.blocks[0].saveFrames, ...carbCompDic.result.blocks[0].saveFrames];
|
||||
const frames: CifFrame[] = [...mmcifDic.result.blocks[0].saveFrames, ...ihmDic.result.blocks[0].saveFrames, ...maDic.result.blocks[0].saveFrames];
|
||||
const schema = generateSchema(frames);
|
||||
|
||||
await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases);
|
||||
@@ -139,8 +135,7 @@ async function getFieldNamesFilter(fieldNamesPath: string): Promise<Filter> {
|
||||
|
||||
async function ensureMmcifDicAvailable() { await ensureDicAvailable(MMCIF_DIC_PATH, MMCIF_DIC_URL); }
|
||||
async function ensureIhmDicAvailable() { await ensureDicAvailable(IHM_DIC_PATH, IHM_DIC_URL); }
|
||||
async function ensureCarbBranchDicAvailable() { await ensureDicAvailable(CARB_BRANCH_DIC_PATH, CARB_BRANCH_DIC_URL); }
|
||||
async function ensureCarbCompDicAvailable() { await ensureDicAvailable(CARB_COMP_DIC_PATH, CARB_COMP_DIC_URL); }
|
||||
async function ensureMaDicAvailable() { await ensureDicAvailable(MA_DIC_PATH, MA_DIC_URL); }
|
||||
async function ensureCifCoreDicAvailable() {
|
||||
await ensureDicAvailable(CIF_CORE_DIC_PATH, CIF_CORE_DIC_URL);
|
||||
await ensureDicAvailable(CIF_CORE_ENUM_PATH, CIF_CORE_ENUM_URL);
|
||||
@@ -165,10 +160,8 @@ const MMCIF_DIC_PATH = `${DIC_DIR}/mmcif_pdbx_v50.dic`;
|
||||
const MMCIF_DIC_URL = 'http://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic';
|
||||
const IHM_DIC_PATH = `${DIC_DIR}/ihm-extension.dic`;
|
||||
const IHM_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/IHM-dictionary/master/ihm-extension.dic';
|
||||
const CARB_BRANCH_DIC_PATH = `${DIC_DIR}/entity_branch-extension.dic`;
|
||||
const CARB_BRANCH_DIC_URL = 'https://raw.githubusercontent.com/pdbxmmcifwg/carbohydrate-extension/master/dict/entity_branch-extension.dic';
|
||||
const CARB_COMP_DIC_PATH = `${DIC_DIR}/chem_comp-extension.dic`;
|
||||
const CARB_COMP_DIC_URL = 'https://raw.githubusercontent.com/pdbxmmcifwg/carbohydrate-extension/master/dict/chem_comp-extension.dic';
|
||||
const MA_DIC_PATH = `${DIC_DIR}/ma-extension.dic`;
|
||||
const MA_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/MA-dictionary/master/mmcif_ma.dic';
|
||||
|
||||
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';
|
||||
|
||||
@@ -57,5 +57,6 @@
|
||||
<script>
|
||||
AlphaOrbitalsExample.init('app')
|
||||
</script>
|
||||
<!-- __MOLSTAR_ANALYTICS__ -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,7 +11,7 @@ import { SphericalBasisOrder } from '../../extensions/alpha-orbitals/spherical-f
|
||||
import { BasisAndOrbitals, CreateOrbitalDensityVolume, CreateOrbitalRepresentation3D, CreateOrbitalVolume, StaticBasisAndOrbitals } from '../../extensions/alpha-orbitals/transforms';
|
||||
import { canComputeGrid3dOnGPU } from '../../mol-gl/compute/grid3d';
|
||||
import { PluginStateObject } from '../../mol-plugin-state/objects';
|
||||
import { createPluginAsync } from '../../mol-plugin-ui';
|
||||
import { createPluginUI } from '../../mol-plugin-ui';
|
||||
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
||||
import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
@@ -54,7 +54,7 @@ export class AlphaOrbitalsExample {
|
||||
|
||||
async init(target: string | HTMLElement) {
|
||||
const defaultSpec = DefaultPluginUISpec();
|
||||
this.plugin = await createPluginAsync(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
...defaultSpec,
|
||||
layout: {
|
||||
initial: {
|
||||
@@ -67,7 +67,7 @@ export class AlphaOrbitalsExample {
|
||||
},
|
||||
canvas3d: {
|
||||
camera: {
|
||||
helper: { axes: { name: 'off', params: { } } }
|
||||
helper: { axes: { name: 'off', params: {} } }
|
||||
}
|
||||
},
|
||||
config: [
|
||||
@@ -170,12 +170,11 @@ export class AlphaOrbitalsExample {
|
||||
return {
|
||||
alpha: 0.85,
|
||||
color,
|
||||
directVolume: this.state.value.gpuSurface,
|
||||
kind,
|
||||
relativeIsovalue: this.state.value.isoValue,
|
||||
pickable: false,
|
||||
xrayShaded: true,
|
||||
tryUseGpu: false
|
||||
tryUseGpu: true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -69,8 +69,9 @@
|
||||
$('format').value = format;
|
||||
$('format').onchange = function (e) { format = e.target.value; }
|
||||
|
||||
BasicMolStarWrapper.init('app' /** or document.getElementById('app') */);
|
||||
BasicMolStarWrapper.setBackground(0xffffff);
|
||||
BasicMolStarWrapper.init('app' /** or document.getElementById('app') */).then(() => {
|
||||
BasicMolStarWrapper.setBackground(0xffffff);
|
||||
});
|
||||
|
||||
addControl('Load Asym Unit', () => BasicMolStarWrapper.load({ url: url, format: format }));
|
||||
addControl('Load Assembly', () => BasicMolStarWrapper.load({ url: url, format: format, assemblyId: assemblyId }));
|
||||
|
||||
@@ -9,7 +9,7 @@ import { EmptyLoci } from '../../mol-model/loci';
|
||||
import { StructureSelection } from '../../mol-model/structure';
|
||||
import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/model-index';
|
||||
import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
|
||||
import { createPlugin } from '../../mol-plugin-ui';
|
||||
import { createPluginUI } from '../../mol-plugin-ui';
|
||||
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
||||
import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
@@ -28,8 +28,8 @@ type LoadParams = { url: string, format?: BuiltInTrajectoryFormat, isBinary?: bo
|
||||
class BasicWrapper {
|
||||
plugin: PluginUIContext;
|
||||
|
||||
init(target: string | HTMLElement) {
|
||||
this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
async init(target: string | HTMLElement) {
|
||||
this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
...DefaultPluginUISpec(),
|
||||
layout: {
|
||||
initial: {
|
||||
@@ -60,7 +60,7 @@ class BasicWrapper {
|
||||
params: { id: assemblyId }
|
||||
} : {
|
||||
name: 'model',
|
||||
params: { }
|
||||
params: {}
|
||||
},
|
||||
showUnitcell: false,
|
||||
representationPreset: 'auto'
|
||||
@@ -95,7 +95,7 @@ class BasicWrapper {
|
||||
loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'loop', params: { direction: 'forward' } } }); },
|
||||
stop: () => this.plugin.managers.animation.stop()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
coloring = {
|
||||
applyStripes: async () => {
|
||||
@@ -119,7 +119,7 @@ class BasicWrapper {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
interactivity = {
|
||||
highlightOn: () => {
|
||||
@@ -137,7 +137,7 @@ class BasicWrapper {
|
||||
clearHighlight: () => {
|
||||
this.plugin.managers.interactivity.lociHighlights.highlightOnly({ loci: EmptyLoci });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tests = {
|
||||
staticSuperposition: async () => {
|
||||
@@ -168,7 +168,7 @@ class BasicWrapper {
|
||||
PluginCommands.Toast.Hide(this.plugin, { key: 'toast-1' });
|
||||
PluginCommands.Toast.Hide(this.plugin, { key: 'toast-2' });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
(window as any).BasicMolStarWrapper = new BasicWrapper();
|
||||
@@ -45,8 +45,9 @@
|
||||
<div id='controls'></div>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
LightingDemo.init('app')
|
||||
LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3)
|
||||
LightingDemo.init('app').then(() => {
|
||||
LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3);
|
||||
});
|
||||
|
||||
addHeader('Example PDB IDs');
|
||||
addControl('4KTC', () => LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3));
|
||||
@@ -83,5 +84,6 @@
|
||||
$('controls').appendChild(h);
|
||||
}
|
||||
</script>
|
||||
<!-- __MOLSTAR_ANALYTICS__ -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,59 +1,62 @@
|
||||
/**
|
||||
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { Canvas3DProps } from '../../mol-canvas3d/canvas3d';
|
||||
import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory';
|
||||
import { createPlugin } from '../../mol-plugin-ui';
|
||||
import { createPluginUI } from '../../mol-plugin-ui';
|
||||
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
||||
import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
import { Asset } from '../../mol-util/assets';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import './index.html';
|
||||
require('mol-plugin-ui/skin/light.scss');
|
||||
|
||||
type LoadParams = { url: string, format?: BuiltInTrajectoryFormat, isBinary?: boolean, assemblyId?: string }
|
||||
|
||||
type _Preset = Pick<Canvas3DProps, 'multiSample' | 'postprocessing' | 'renderer'>
|
||||
type _Preset = Pick<Canvas3DProps, 'postprocessing' | 'renderer'>
|
||||
type Preset = { [K in keyof _Preset]: Partial<_Preset[K]> }
|
||||
|
||||
const Canvas3DPresets = {
|
||||
illustrative: <Preset> {
|
||||
multiSample: {
|
||||
mode: 'temporal' as Canvas3DProps['multiSample']['mode']
|
||||
},
|
||||
postprocessing: {
|
||||
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } },
|
||||
outline: { name: 'on', params: { scale: 1, threshold: 0.1 } }
|
||||
},
|
||||
renderer: {
|
||||
style: { name: 'flat', params: {} }
|
||||
illustrative: {
|
||||
canvas3d: <Preset>{
|
||||
postprocessing: {
|
||||
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } },
|
||||
outline: { name: 'on', params: { scale: 1, threshold: 0.33, color: Color(0x000000) } }
|
||||
},
|
||||
renderer: {
|
||||
ambientIntensity: 1.0,
|
||||
light: []
|
||||
}
|
||||
}
|
||||
},
|
||||
occlusion: <Preset> {
|
||||
multiSample: {
|
||||
mode: 'temporal' as Canvas3DProps['multiSample']['mode']
|
||||
},
|
||||
postprocessing: {
|
||||
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } },
|
||||
outline: { name: 'off', params: { } }
|
||||
},
|
||||
renderer: {
|
||||
style: { name: 'matte', params: {} }
|
||||
occlusion: {
|
||||
canvas3d: <Preset>{
|
||||
postprocessing: {
|
||||
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } },
|
||||
outline: { name: 'off', params: {} }
|
||||
},
|
||||
renderer: {
|
||||
ambientIntensity: 0.4,
|
||||
light: [{ inclination: 180, azimuth: 0, color: Color.fromNormalizedRgb(1.0, 1.0, 1.0),
|
||||
intensity: 0.6 }]
|
||||
}
|
||||
}
|
||||
},
|
||||
standard: <Preset> {
|
||||
multiSample: {
|
||||
mode: 'off' as Canvas3DProps['multiSample']['mode']
|
||||
},
|
||||
postprocessing: {
|
||||
occlusion: { name: 'off', params: { } },
|
||||
outline: { name: 'off', params: { } }
|
||||
},
|
||||
renderer: {
|
||||
style: { name: 'matte', params: {} }
|
||||
standard: {
|
||||
canvas3d: <Preset>{
|
||||
postprocessing: {
|
||||
occlusion: { name: 'off', params: {} },
|
||||
outline: { name: 'off', params: {} }
|
||||
},
|
||||
renderer: {
|
||||
ambientIntensity: 0.4,
|
||||
light: [{ inclination: 180, azimuth: 0, color: Color.fromNormalizedRgb(1.0, 1.0, 1.0),
|
||||
intensity: 0.6 }]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -68,8 +71,8 @@ class LightingDemo {
|
||||
private bias = 1.1;
|
||||
private preset: Canvas3DPreset = 'illustrative';
|
||||
|
||||
init(target: string | HTMLElement) {
|
||||
this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
async init(target: string | HTMLElement) {
|
||||
this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
...DefaultPluginUISpec(),
|
||||
layout: {
|
||||
initial: {
|
||||
@@ -87,25 +90,23 @@ class LightingDemo {
|
||||
|
||||
setPreset(preset: Canvas3DPreset) {
|
||||
const props = Canvas3DPresets[preset];
|
||||
if (props.postprocessing.occlusion?.name === 'on') {
|
||||
props.postprocessing.occlusion.params.radius = this.radius;
|
||||
props.postprocessing.occlusion.params.bias = this.bias;
|
||||
if (props.canvas3d.postprocessing.occlusion?.name === 'on') {
|
||||
props.canvas3d.postprocessing.occlusion.params.radius = this.radius;
|
||||
props.canvas3d.postprocessing.occlusion.params.bias = this.bias;
|
||||
}
|
||||
PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: {
|
||||
...props,
|
||||
multiSample: {
|
||||
...this.plugin.canvas3d!.props.multiSample,
|
||||
...props.multiSample
|
||||
},
|
||||
renderer: {
|
||||
...this.plugin.canvas3d!.props.renderer,
|
||||
...props.renderer
|
||||
},
|
||||
postprocessing: {
|
||||
...this.plugin.canvas3d!.props.postprocessing,
|
||||
...props.postprocessing
|
||||
},
|
||||
} });
|
||||
PluginCommands.Canvas3D.SetSettings(this.plugin, {
|
||||
settings: {
|
||||
...props,
|
||||
renderer: {
|
||||
...this.plugin.canvas3d!.props.renderer,
|
||||
...props.canvas3d.renderer
|
||||
},
|
||||
postprocessing: {
|
||||
...this.plugin.canvas3d!.props.postprocessing,
|
||||
...props.canvas3d.postprocessing
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async load({ url, format = 'mmcif', isBinary = true, assemblyId = '' }: LoadParams, radius: number, bias: number) {
|
||||
@@ -114,7 +115,7 @@ class LightingDemo {
|
||||
const data = await this.plugin.builders.data.download({ url: Asset.Url(url), isBinary }, { state: { isGhost: true } });
|
||||
const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format);
|
||||
const model = await this.plugin.builders.structure.createModel(trajectory);
|
||||
const structure = await this.plugin.builders.structure.createStructure(model, assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'model', params: { } });
|
||||
const structure = await this.plugin.builders.structure.createStructure(model, assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'model', params: {} });
|
||||
|
||||
const polymer = await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'polymer');
|
||||
if (polymer) await this.plugin.builders.structure.representation.addRepresentation(polymer, { type: 'spacefill', color: 'illustrative' });
|
||||
|
||||
@@ -103,10 +103,11 @@
|
||||
|
||||
PluginWrapper.init('app' /** or document.getElementById('app') */, {
|
||||
customColorList: CustomColors
|
||||
}).then(() => {
|
||||
PluginWrapper.setBackground(0xffffff);
|
||||
loadAndSnapshot({ url: url, format: format, isBinary: isBinary, assemblyId: assemblyId, representationStyle: representationStyle });
|
||||
PluginWrapper.toggleSpin();
|
||||
});
|
||||
PluginWrapper.setBackground(0xffffff);
|
||||
loadAndSnapshot({ url: url, format: format, isBinary: isBinary, assemblyId: assemblyId, representationStyle: representationStyle });
|
||||
PluginWrapper.toggleSpin();
|
||||
|
||||
PluginWrapper.events.modelInfo.subscribe(function (info) {
|
||||
console.log('Model Info', info);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/mod
|
||||
import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params';
|
||||
import { PluginStateObject, PluginStateObject as PSO } from '../../mol-plugin-state/objects';
|
||||
import { StateTransforms } from '../../mol-plugin-state/transforms';
|
||||
import { createPlugin } from '../../mol-plugin-ui';
|
||||
import { createPluginUI } from '../../mol-plugin-ui';
|
||||
import { PluginUIContext } from '../../mol-plugin-ui/context';
|
||||
import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec';
|
||||
import { CreateVolumeStreamingInfo, InitVolumeStreaming } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
|
||||
@@ -43,10 +43,10 @@ class MolStarProteopediaWrapper {
|
||||
|
||||
plugin: PluginUIContext;
|
||||
|
||||
init(target: string | HTMLElement, options?: {
|
||||
async init(target: string | HTMLElement, options?: {
|
||||
customColorList?: number[]
|
||||
}) {
|
||||
this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, {
|
||||
...DefaultPluginUISpec(),
|
||||
animations: [
|
||||
AnimateModelIndex
|
||||
@@ -95,7 +95,7 @@ class MolStarProteopediaWrapper {
|
||||
params: { id: assemblyId }
|
||||
} : {
|
||||
name: 'model' as const,
|
||||
params: { }
|
||||
params: {}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,7 +113,7 @@ class MolStarProteopediaWrapper {
|
||||
const structure = this.getObj<PluginStateObject.Molecule.Structure>(StateElements.Assembly);
|
||||
if (!structure) return;
|
||||
|
||||
const style = _style || { };
|
||||
const style = _style || {};
|
||||
|
||||
const update = this.state.build();
|
||||
|
||||
@@ -229,7 +229,7 @@ class MolStarProteopediaWrapper {
|
||||
params: { id: asmId }
|
||||
} : {
|
||||
name: 'model' as const,
|
||||
params: { }
|
||||
params: {}
|
||||
}
|
||||
};
|
||||
tree.to(StateElements.Assembly).update(StateTransforms.Model.StructureFromModel, p => ({ ...p, ...props }));
|
||||
@@ -269,8 +269,8 @@ class MolStarProteopediaWrapper {
|
||||
|
||||
camera = {
|
||||
toggleSpin: () => this.toggleSpin(),
|
||||
resetPosition: () => PluginCommands.Camera.Reset(this.plugin, { })
|
||||
}
|
||||
resetPosition: () => PluginCommands.Camera.Reset(this.plugin, {})
|
||||
};
|
||||
|
||||
private animateModelIndexTargetFps() {
|
||||
return Math.max(1, this.animate.modelIndex.targetFps | 0);
|
||||
@@ -285,7 +285,7 @@ class MolStarProteopediaWrapper {
|
||||
loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'loop', params: { direction: 'forward' } } }); },
|
||||
stop: () => this.plugin.managers.animation.stop()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
coloring = {
|
||||
evolutionaryConservation: async (params?: { sequence?: boolean, het?: boolean, keepStyle?: boolean }) => {
|
||||
@@ -306,7 +306,7 @@ class MolStarProteopediaWrapper {
|
||||
|
||||
await PluginCommands.State.Update(this.plugin, { state, tree });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private experimentalDataElement?: Element = void 0;
|
||||
experimentalData = {
|
||||
@@ -330,17 +330,17 @@ class MolStarProteopediaWrapper {
|
||||
this.experimentalDataElement = void 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
hetGroups = {
|
||||
reset: () => {
|
||||
const update = this.state.build().delete(StateElements.HetGroupFocusGroup);
|
||||
PluginCommands.State.Update(this.plugin, { state: this.state, tree: update });
|
||||
PluginCommands.Camera.Reset(this.plugin, { });
|
||||
PluginCommands.Camera.Reset(this.plugin, {});
|
||||
},
|
||||
focusFirst: async (compId: string, options?: { hideLabels: boolean, doNotLabelWaters: boolean }) => {
|
||||
if (!this.state.transforms.has(StateElements.Assembly)) return;
|
||||
await PluginCommands.Camera.Reset(this.plugin, { });
|
||||
await PluginCommands.Camera.Reset(this.plugin, {});
|
||||
|
||||
const update = this.state.build();
|
||||
|
||||
@@ -397,7 +397,7 @@ class MolStarProteopediaWrapper {
|
||||
const snapshot = this.plugin.canvas3d!.camera.getFocus(sphere.center, radius);
|
||||
PluginCommands.Camera.SetSnapshot(this.plugin, { snapshot, durationMs: 250 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
snapshot = {
|
||||
get: (params?: PluginState.SnapshotParams) => {
|
||||
@@ -420,7 +420,7 @@ class MolStarProteopediaWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
(window as any).MolStarProteopediaWrapper = MolStarProteopediaWrapper;
|
||||
@@ -166,7 +166,6 @@ export const CreateOrbitalRepresentation3D = PluginStateTransform.BuiltIn({
|
||||
from: PluginStateObject.Volume.Data,
|
||||
to: PluginStateObject.Volume.Representation3D,
|
||||
params: {
|
||||
directVolume: PD.Boolean(false),
|
||||
relativeIsovalue: PD.Numeric(1, { min: 0.01, max: 5, step: 0.01 }),
|
||||
kind: PD.Select<'positive' | 'negative'>('positive', [['positive', 'Positive'], ['negative', 'Negative']]),
|
||||
color: PD.Color(ColorNames.blue),
|
||||
@@ -217,19 +216,7 @@ function volumeParams(plugin: PluginContext, volume: PluginStateObject.Volume.Da
|
||||
|
||||
const value = isovalues[params.kind];
|
||||
|
||||
return createVolumeRepresentationParams(plugin, volume.data, params.directVolume ? {
|
||||
type: 'direct-volume',
|
||||
typeParams: {
|
||||
alpha: params.alpha,
|
||||
renderMode: {
|
||||
name: 'isosurface',
|
||||
params: { isoValue: { kind: 'absolute', absoluteValue: (value ?? 1000) * params.relativeIsovalue }, singleLayer: false }
|
||||
},
|
||||
xrayShaded: params.xrayShaded
|
||||
},
|
||||
color: 'uniform',
|
||||
colorParams: { value: params.color }
|
||||
} : {
|
||||
return createVolumeRepresentationParams(plugin, volume.data, {
|
||||
type: 'isosurface',
|
||||
typeParams: { isoValue: { kind: 'absolute', absoluteValue: (value ?? 1000) * params.relativeIsovalue }, alpha: params.alpha, xrayShaded: params.xrayShaded, tryUseGpu: params.tryUseGpu },
|
||||
color: 'uniform',
|
||||
|
||||
@@ -30,7 +30,7 @@ export const ANVILMembraneOrientation = PluginBehavior.create<{ autoAttach: bool
|
||||
description: 'Data calculated with ANVIL algorithm.'
|
||||
},
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean }> {
|
||||
private provider = MembraneOrientationProvider
|
||||
private provider = MembraneOrientationProvider;
|
||||
|
||||
register(): void {
|
||||
DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor);
|
||||
|
||||
@@ -66,7 +66,7 @@ export const DnatcoConfalPyramids = PluginBehavior.create<{ autoAttach: boolean,
|
||||
/* TODO: Implement this */
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
register(): void {
|
||||
this.ctx.customModelProperties.register(this.provider, this.params.autoAttach);
|
||||
|
||||
@@ -114,7 +114,7 @@ export namespace ConfalPyramidsUtil {
|
||||
this.modelNum = unit.model.modelNum;
|
||||
}
|
||||
|
||||
protected readonly data: CPT.PyramidsData
|
||||
protected readonly data: CPT.PyramidsData;
|
||||
protected readonly hasMultipleModels: boolean;
|
||||
protected readonly entryId: string;
|
||||
protected readonly modelNum: number;
|
||||
|
||||
@@ -29,7 +29,7 @@ export const GeometryParams = {
|
||||
export class GeometryControls extends PluginComponent {
|
||||
readonly behaviors = {
|
||||
params: this.ev.behavior<PD.Values<typeof GeometryParams>>(PD.getDefaultValues(GeometryParams))
|
||||
}
|
||||
};
|
||||
|
||||
private getFilename() {
|
||||
const models = this.plugin.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Model)).map(s => s.obj!.data);
|
||||
|
||||
@@ -145,7 +145,7 @@ export class ObjExporter extends MeshExporter<ObjData> {
|
||||
const color = ObjExporter.getColor(v, geoData, interpolatedColors, interpolatedOverpaint);
|
||||
Color.toArray(color, quantizedColors, i);
|
||||
}
|
||||
ObjExporter.quantizeColors(quantizedColors, mesh!.vertexCount);
|
||||
ObjExporter.quantizeColors(quantizedColors, vertexCount);
|
||||
|
||||
// face
|
||||
for (let i = 0; i < drawCount; i += 3) {
|
||||
|
||||
@@ -85,7 +85,7 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
|
||||
} finally {
|
||||
this.setState({ busy: false });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
viewInAR = async () => {
|
||||
try {
|
||||
@@ -104,5 +104,5 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
|
||||
} finally {
|
||||
this.setState({ busy: false });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -149,7 +149,7 @@ def Material "material${materialKey}"
|
||||
const color = UsdzExporter.getColor(v, geoData, interpolatedColors, interpolatedOverpaint);
|
||||
Color.toArray(color, quantizedColors, i);
|
||||
}
|
||||
UsdzExporter.quantizeColors(quantizedColors, mesh!.vertexCount);
|
||||
UsdzExporter.quantizeColors(quantizedColors, vertexCount);
|
||||
|
||||
// material
|
||||
const faceIndicesByMaterial = new Map<number, number[]>();
|
||||
|
||||
212
src/extensions/model-archive/quality-assessment/behavior.ts
Normal file
212
src/extensions/model-archive/quality-assessment/behavior.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
|
||||
import { PluginBehavior } from '../../../mol-plugin/behavior/behavior';
|
||||
import { Loci } from '../../../mol-model/loci';
|
||||
import { DefaultQueryRuntimeTable } from '../../../mol-script/runtime/query/compiler';
|
||||
import { PLDDTConfidenceColorThemeProvider } from './color/plddt';
|
||||
import { QualityAssessment, QualityAssessmentProvider } from './prop';
|
||||
import { StructureSelectionCategory, StructureSelectionQuery } from '../../../mol-plugin-state/helpers/structure-selection-query';
|
||||
import { MolScriptBuilder as MS } from '../../../mol-script/language/builder';
|
||||
import { OrderedSet } from '../../../mol-data/int';
|
||||
import { cantorPairing } from '../../../mol-data/util';
|
||||
import { QmeanScoreColorThemeProvider } from './color/qmean';
|
||||
import { PresetStructureRepresentations, StructureRepresentationPresetProvider } from '../../../mol-plugin-state/builder/structure/representation-preset';
|
||||
import { StateObjectRef } from '../../../mol-state';
|
||||
|
||||
export const MAQualityAssessment = PluginBehavior.create<{ autoAttach: boolean, showTooltip: boolean }>({
|
||||
name: 'ma-quality-assessment-prop',
|
||||
category: 'custom-props',
|
||||
display: {
|
||||
name: 'Quality Assessment',
|
||||
description: 'Data included in Model Archive files.'
|
||||
},
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
|
||||
private provider = QualityAssessmentProvider
|
||||
|
||||
private labelProvider = {
|
||||
label: (loci: Loci): string | undefined => {
|
||||
if (!this.params.showTooltip) return;
|
||||
return [
|
||||
plddtLabel(loci),
|
||||
qmeanLabel(loci),
|
||||
].filter(l => !!l).join('</br>');
|
||||
}
|
||||
}
|
||||
|
||||
register(): void {
|
||||
DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor);
|
||||
|
||||
this.ctx.customModelProperties.register(this.provider, this.params.autoAttach);
|
||||
|
||||
this.ctx.managers.lociLabels.addProvider(this.labelProvider);
|
||||
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.add(PLDDTConfidenceColorThemeProvider);
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.add(QmeanScoreColorThemeProvider);
|
||||
|
||||
this.ctx.query.structure.registry.add(confidentPLDDT);
|
||||
|
||||
this.ctx.builders.structure.representation.registerPreset(QualityAssessmentPLDDTPreset);
|
||||
this.ctx.builders.structure.representation.registerPreset(QualityAssessmentQmeanPreset);
|
||||
}
|
||||
|
||||
update(p: { autoAttach: boolean, showTooltip: boolean }) {
|
||||
const updated = this.params.autoAttach !== p.autoAttach;
|
||||
this.params.autoAttach = p.autoAttach;
|
||||
this.params.showTooltip = p.showTooltip;
|
||||
this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach);
|
||||
return updated;
|
||||
}
|
||||
|
||||
unregister() {
|
||||
DefaultQueryRuntimeTable.removeCustomProp(this.provider.descriptor);
|
||||
|
||||
this.ctx.customStructureProperties.unregister(this.provider.descriptor.name);
|
||||
|
||||
this.ctx.managers.lociLabels.removeProvider(this.labelProvider);
|
||||
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.remove(PLDDTConfidenceColorThemeProvider);
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.remove(QmeanScoreColorThemeProvider);
|
||||
|
||||
this.ctx.query.structure.registry.remove(confidentPLDDT);
|
||||
|
||||
this.ctx.builders.structure.representation.unregisterPreset(QualityAssessmentPLDDTPreset);
|
||||
this.ctx.builders.structure.representation.unregisterPreset(QualityAssessmentQmeanPreset);
|
||||
}
|
||||
},
|
||||
params: () => ({
|
||||
autoAttach: PD.Boolean(false),
|
||||
showTooltip: PD.Boolean(true),
|
||||
})
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
function plddtCategory(score: number) {
|
||||
if (score > 50 && score <= 70) return 'Low';
|
||||
if (score > 70 && score <= 90) return 'Confident';
|
||||
if (score > 90) return 'Very high';
|
||||
return 'Very low';
|
||||
}
|
||||
|
||||
function plddtLabel(loci: Loci): string | undefined {
|
||||
return metricLabel(loci, 'pLDDT', (scoreAvg: number, countInfo: string) => `pLDDT Score ${countInfo}: ${scoreAvg.toFixed(2)} <small>(${plddtCategory(scoreAvg)})</small>`);
|
||||
}
|
||||
|
||||
function qmeanLabel(loci: Loci): string | undefined {
|
||||
return metricLabel(loci, 'qmean', (scoreAvg: number, countInfo: string) => `QMEAN Score ${countInfo}: ${scoreAvg.toFixed(2)}`);
|
||||
}
|
||||
|
||||
function metricLabel(loci: Loci, name: 'qmean' | 'pLDDT', label: (scoreAvg: number, countInfo: string) => string): string | undefined {
|
||||
if (loci.kind === 'element-loci') {
|
||||
if (loci.elements.length === 0) return;
|
||||
|
||||
const seen = new Set<number>();
|
||||
const scoreSeen = new Set<number>();
|
||||
let scoreSum = 0;
|
||||
|
||||
for (const { indices, unit } of loci.elements) {
|
||||
const metric = QualityAssessmentProvider.get(unit.model).value?.[name];
|
||||
if (!metric) continue;
|
||||
|
||||
const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index;
|
||||
const { elements } = unit;
|
||||
|
||||
OrderedSet.forEach(indices, idx => {
|
||||
const eI = elements[idx];
|
||||
const rI = residueIndex[eI];
|
||||
|
||||
const residueKey = cantorPairing(rI, unit.id);
|
||||
if (!seen.has(residueKey)) {
|
||||
const score = metric.get(residueIndex[eI]) ?? -1;
|
||||
if (score !== -1) {
|
||||
scoreSum += score;
|
||||
scoreSeen.add(residueKey);
|
||||
}
|
||||
seen.add(residueKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (seen.size === 0) return;
|
||||
|
||||
const summary: string[] = [];
|
||||
|
||||
if (scoreSeen.size) {
|
||||
const countInfo = `<small>(${scoreSeen.size} ${scoreSeen.size > 1 ? 'Residues avg.' : 'Residue'})</small>`;
|
||||
const scoreAvg = scoreSum / scoreSeen.size;
|
||||
summary.push(label(scoreAvg, countInfo));
|
||||
}
|
||||
|
||||
if (summary.length) {
|
||||
return summary.join('</br>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const confidentPLDDT = StructureSelectionQuery('Confident pLDDT (> 70)', MS.struct.modifier.union([
|
||||
MS.struct.modifier.wholeResidues([
|
||||
MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.rel.gr([QualityAssessment.symbols.pLDDT.symbol(), 70]),
|
||||
})
|
||||
])
|
||||
])
|
||||
]), {
|
||||
description: 'Select residues with a pLDDT > 70 (confident).',
|
||||
category: StructureSelectionCategory.Validation,
|
||||
ensureCustomProperties: async (ctx, structure) => {
|
||||
for (const m of structure.models) {
|
||||
await QualityAssessmentProvider.attach(ctx, m, void 0, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
export const QualityAssessmentPLDDTPreset = StructureRepresentationPresetProvider({
|
||||
id: 'preset-structure-representation-ma-quality-assessment-plddt',
|
||||
display: {
|
||||
name: 'Quality Assessment (pLDDT)', group: 'Annotation',
|
||||
description: 'Color structure based on pLDDT Confidence.'
|
||||
},
|
||||
isApplicable(a) {
|
||||
return !!a.data.models.some(m => QualityAssessment.isApplicable(m, 'pLDDT'));
|
||||
},
|
||||
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 {};
|
||||
|
||||
const colorTheme = PLDDTConfidenceColorThemeProvider.name as any;
|
||||
return await PresetStructureRepresentations.auto.apply(ref, { ...params, theme: { globalName: colorTheme, focus: { name: colorTheme } } }, plugin);
|
||||
}
|
||||
});
|
||||
|
||||
export const QualityAssessmentQmeanPreset = StructureRepresentationPresetProvider({
|
||||
id: 'preset-structure-representation-ma-quality-assessment-qmean',
|
||||
display: {
|
||||
name: 'Quality Assessment (QMEAN)', group: 'Annotation',
|
||||
description: 'Color structure based on QMEAN Score.'
|
||||
},
|
||||
isApplicable(a) {
|
||||
return !!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 {};
|
||||
|
||||
const colorTheme = QmeanScoreColorThemeProvider.name as any;
|
||||
return await PresetStructureRepresentations.auto.apply(ref, { ...params, theme: { globalName: colorTheme, focus: { name: colorTheme } } }, plugin);
|
||||
}
|
||||
});
|
||||
106
src/extensions/model-archive/quality-assessment/color/plddt.ts
Normal file
106
src/extensions/model-archive/quality-assessment/color/plddt.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Mandar Deshpande <mandar@ebi.ac.uk>
|
||||
* @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { QualityAssessment, QualityAssessmentProvider } from '../prop';
|
||||
import { Location } from '../../../../mol-model/location';
|
||||
import { Bond, StructureElement, Unit } from '../../../../mol-model/structure';
|
||||
import { ColorTheme, LocationColor } from '../../../../mol-theme/color';
|
||||
import { ThemeDataContext } from '../../../../mol-theme/theme';
|
||||
import { Color } from '../../../../mol-util/color';
|
||||
import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
|
||||
import { CustomProperty } from '../../../../mol-model-props/common/custom-property';
|
||||
import { TableLegend } from '../../../../mol-util/legend';
|
||||
|
||||
const DefaultColor = Color(0xaaaaaa);
|
||||
const ConfidenceColors = {
|
||||
'No Score': DefaultColor,
|
||||
'Very Low': Color(0xff7d45),
|
||||
'Low': Color(0xffdb13),
|
||||
'Confident': Color(0x65cbf3),
|
||||
'Very High': Color(0x0053d6)
|
||||
};
|
||||
|
||||
const ConfidenceColorLegend = TableLegend(Object.entries(ConfidenceColors));
|
||||
|
||||
export function getPLDDTConfidenceColorThemeParams(ctx: ThemeDataContext) {
|
||||
return {};
|
||||
}
|
||||
export type PLDDTConfidenceColorThemeParams = ReturnType<typeof getPLDDTConfidenceColorThemeParams>
|
||||
|
||||
export function PLDDTConfidenceColorTheme(ctx: ThemeDataContext, props: PD.Values<PLDDTConfidenceColorThemeParams>): ColorTheme<PLDDTConfidenceColorThemeParams> {
|
||||
let color: LocationColor = () => DefaultColor;
|
||||
|
||||
if (ctx.structure) {
|
||||
const l = StructureElement.Location.create(ctx.structure.root);
|
||||
|
||||
const getColor = (location: StructureElement.Location): Color => {
|
||||
const { unit, element } = location;
|
||||
if (!Unit.isAtomic(unit)) return DefaultColor;
|
||||
const qualityAssessment = QualityAssessmentProvider.get(unit.model).value;
|
||||
const score = qualityAssessment?.pLDDT?.get(unit.model.atomicHierarchy.residueAtomSegments.index[element]) ?? -1;
|
||||
if (score < 0) {
|
||||
return DefaultColor;
|
||||
} else if (score <= 50) {
|
||||
return Color(0xff7d45);
|
||||
} else if (score <= 70) {
|
||||
return Color(0xffdb13);
|
||||
} else if (score <= 90) {
|
||||
return Color(0x65cbf3);
|
||||
} else {
|
||||
return Color(0x0053d6);
|
||||
}
|
||||
};
|
||||
|
||||
color = (location: Location) => {
|
||||
if (StructureElement.Location.is(location)) {
|
||||
return getColor(location);
|
||||
} else if (Bond.isLocation(location)) {
|
||||
l.unit = location.aUnit;
|
||||
l.element = location.aUnit.elements[location.aIndex];
|
||||
return getColor(l);
|
||||
}
|
||||
return DefaultColor;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
factory: PLDDTConfidenceColorTheme,
|
||||
granularity: 'group',
|
||||
preferSmoothing: true,
|
||||
color,
|
||||
props,
|
||||
description: 'Assigns residue colors according to the pLDDT Confidence score.',
|
||||
legend: ConfidenceColorLegend
|
||||
};
|
||||
}
|
||||
|
||||
export const PLDDTConfidenceColorThemeProvider: ColorTheme.Provider<PLDDTConfidenceColorThemeParams, 'plddt-confidence'> = {
|
||||
name: 'plddt-confidence',
|
||||
label: 'pLDDT Confidence',
|
||||
category: ColorTheme.Category.Validation,
|
||||
factory: PLDDTConfidenceColorTheme,
|
||||
getParams: getPLDDTConfidenceColorThemeParams,
|
||||
defaultValues: PD.getDefaultValues(getPLDDTConfidenceColorThemeParams({})),
|
||||
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure?.models.some(m => QualityAssessment.isApplicable(m, 'pLDDT')),
|
||||
ensureCustomProperties: {
|
||||
attach: async (ctx: CustomProperty.Context, data: ThemeDataContext) => {
|
||||
if (data.structure) {
|
||||
for (const m of data.structure.models) {
|
||||
await QualityAssessmentProvider.attach(ctx, m, void 0, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
detach: async (data: ThemeDataContext) => {
|
||||
if (data.structure) {
|
||||
for (const m of data.structure.models) {
|
||||
QualityAssessmentProvider.ref(m, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { QualityAssessment, QualityAssessmentProvider } from '../prop';
|
||||
import { Location } from '../../../../mol-model/location';
|
||||
import { Bond, StructureElement, Unit } from '../../../../mol-model/structure';
|
||||
import { ColorTheme, LocationColor } from '../../../../mol-theme/color';
|
||||
import { ThemeDataContext } from '../../../../mol-theme/theme';
|
||||
import { Color, ColorScale } from '../../../../mol-util/color';
|
||||
import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
|
||||
import { CustomProperty } from '../../../../mol-model-props/common/custom-property';
|
||||
|
||||
const DefaultColor = Color(0xaaaaaa);
|
||||
|
||||
export function getQmeanScoreColorThemeParams(ctx: ThemeDataContext) {
|
||||
return {};
|
||||
}
|
||||
export type QmeanScoreColorThemeParams = ReturnType<typeof getQmeanScoreColorThemeParams>
|
||||
|
||||
export function QmeanScoreColorTheme(ctx: ThemeDataContext, props: PD.Values<QmeanScoreColorThemeParams>): ColorTheme<QmeanScoreColorThemeParams> {
|
||||
let color: LocationColor = () => DefaultColor;
|
||||
|
||||
const scale = ColorScale.create({
|
||||
domain: [0, 1],
|
||||
listOrName: [
|
||||
[Color(0xFF5000), 0.5], [Color(0x025AFD), 1.0]
|
||||
]
|
||||
});
|
||||
|
||||
if (ctx.structure) {
|
||||
const l = StructureElement.Location.create(ctx.structure.root);
|
||||
|
||||
const getColor = (location: StructureElement.Location): Color => {
|
||||
const { unit, element } = location;
|
||||
if (!Unit.isAtomic(unit)) return DefaultColor;
|
||||
const qualityAssessment = QualityAssessmentProvider.get(unit.model).value;
|
||||
const score = qualityAssessment?.qmean?.get(unit.model.atomicHierarchy.residueAtomSegments.index[element]) ?? -1;
|
||||
if (score < 0) {
|
||||
return DefaultColor;
|
||||
} else {
|
||||
return scale.color(score);
|
||||
}
|
||||
};
|
||||
|
||||
color = (location: Location) => {
|
||||
if (StructureElement.Location.is(location)) {
|
||||
return getColor(location);
|
||||
} else if (Bond.isLocation(location)) {
|
||||
l.unit = location.aUnit;
|
||||
l.element = location.aUnit.elements[location.aIndex];
|
||||
return getColor(l);
|
||||
}
|
||||
return DefaultColor;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
factory: QmeanScoreColorTheme,
|
||||
granularity: 'group',
|
||||
preferSmoothing: true,
|
||||
color,
|
||||
props,
|
||||
description: 'Assigns residue colors according to the QMEAN score.',
|
||||
legend: scale.legend
|
||||
};
|
||||
}
|
||||
|
||||
export const QmeanScoreColorThemeProvider: ColorTheme.Provider<QmeanScoreColorThemeParams, 'qmean-score'> = {
|
||||
name: 'qmean-score',
|
||||
label: 'QMEAN Score',
|
||||
category: ColorTheme.Category.Validation,
|
||||
factory: QmeanScoreColorTheme,
|
||||
getParams: getQmeanScoreColorThemeParams,
|
||||
defaultValues: PD.getDefaultValues(getQmeanScoreColorThemeParams({})),
|
||||
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure?.models.some(m => QualityAssessment.isApplicable(m, 'qmean')),
|
||||
ensureCustomProperties: {
|
||||
attach: async (ctx: CustomProperty.Context, data: ThemeDataContext) => {
|
||||
if (data.structure) {
|
||||
for (const m of data.structure.models) {
|
||||
await QualityAssessmentProvider.attach(ctx, m, void 0, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
detach: async (data: ThemeDataContext) => {
|
||||
if (data.structure) {
|
||||
for (const m of data.structure.models) {
|
||||
QualityAssessmentProvider.ref(m, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
131
src/extensions/model-archive/quality-assessment/prop.ts
Normal file
131
src/extensions/model-archive/quality-assessment/prop.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
|
||||
import { Unit } from '../../../mol-model/structure';
|
||||
import { CustomProperty } from '../../../mol-model-props/common/custom-property';
|
||||
import { CustomModelProperty } from '../../../mol-model-props/common/custom-model-property';
|
||||
import { Model, ResidueIndex } from '../../../mol-model/structure/model';
|
||||
import { QuerySymbolRuntime } from '../../../mol-script/runtime/query/compiler';
|
||||
import { CustomPropSymbol } from '../../../mol-script/language/symbol';
|
||||
import { Type } from '../../../mol-script/language/type';
|
||||
import { CustomPropertyDescriptor } from '../../../mol-model/custom-property';
|
||||
import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif';
|
||||
|
||||
export { QualityAssessment };
|
||||
|
||||
interface QualityAssessment {
|
||||
localMetrics: Map<string, Map<ResidueIndex, number>>
|
||||
pLDDT?: Map<ResidueIndex, number>
|
||||
qmean?: Map<ResidueIndex, number>
|
||||
}
|
||||
|
||||
namespace QualityAssessment {
|
||||
const Empty = {
|
||||
value: {
|
||||
localMetrics: new Map()
|
||||
}
|
||||
};
|
||||
|
||||
export function isApplicable(model?: Model, localMetricName?: 'pLDDT' | 'qmean'): boolean {
|
||||
if (!model || !MmcifFormat.is(model.sourceData)) return false;
|
||||
const { db } = model.sourceData.data;
|
||||
const hasLocalMetric = (
|
||||
db.ma_qa_metric.id.isDefined &&
|
||||
db.ma_qa_metric_local.ordinal_id.isDefined
|
||||
);
|
||||
if (localMetricName && hasLocalMetric) {
|
||||
for (let i = 0, il = db.ma_qa_metric._rowCount; i < il; i++) {
|
||||
if (db.ma_qa_metric.mode.value(i) !== 'local') continue;
|
||||
if (localMetricName === db.ma_qa_metric.name.value(i)) return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return hasLocalMetric;
|
||||
}
|
||||
}
|
||||
|
||||
export async function obtain(ctx: CustomProperty.Context, model: Model, props: QualityAssessmentProps): Promise<CustomProperty.Data<QualityAssessment>> {
|
||||
if (!model || !MmcifFormat.is(model.sourceData)) return Empty;
|
||||
const { ma_qa_metric, ma_qa_metric_local } = model.sourceData.data.db;
|
||||
const { model_id, label_asym_id, label_seq_id, metric_id, metric_value } = ma_qa_metric_local;
|
||||
const { index } = model.atomicHierarchy;
|
||||
|
||||
// for simplicity we assume names in ma_qa_metric for mode 'local' are unique
|
||||
const localMetrics = new Map<string, Map<ResidueIndex, number>>();
|
||||
const localNames = new Map<number, string>();
|
||||
|
||||
for (let i = 0, il = ma_qa_metric._rowCount; i < il; i++) {
|
||||
if (ma_qa_metric.mode.value(i) !== 'local') continue;
|
||||
|
||||
const name = ma_qa_metric.name.value(i);
|
||||
if (localMetrics.has(name)) {
|
||||
console.warn(`local ma_qa_metric with name '${name}' already added`);
|
||||
continue;
|
||||
}
|
||||
|
||||
localMetrics.set(name, new Map());
|
||||
localNames.set(ma_qa_metric.id.value(i), name);
|
||||
}
|
||||
|
||||
for (let i = 0, il = ma_qa_metric_local._rowCount; i < il; i++) {
|
||||
if (model_id.value(i) !== model.modelNum) continue;
|
||||
|
||||
const labelAsymId = label_asym_id.value(i);
|
||||
const entityIndex = index.findEntity(labelAsymId);
|
||||
const rI = index.findResidue(model.entities.data.id.value(entityIndex), labelAsymId, label_seq_id.value(i));
|
||||
const name = localNames.get(metric_id.value(i))!;
|
||||
localMetrics.get(name)!.set(rI, metric_value.value(i));
|
||||
}
|
||||
|
||||
return {
|
||||
value: {
|
||||
localMetrics,
|
||||
pLDDT: localMetrics.get('pLDDT'),
|
||||
qmean: localMetrics.get('qmean'),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const symbols = {
|
||||
pLDDT: QuerySymbolRuntime.Dynamic(CustomPropSymbol('ma', 'quality-assessment.pLDDT', Type.Num),
|
||||
ctx => {
|
||||
const { unit, element } = ctx.element;
|
||||
if (!Unit.isAtomic(unit)) return -1;
|
||||
const qualityAssessment = QualityAssessmentProvider.get(unit.model).value;
|
||||
return qualityAssessment?.pLDDT?.get(unit.model.atomicHierarchy.residueAtomSegments.index[element]) ?? -1;
|
||||
}
|
||||
),
|
||||
qmean: QuerySymbolRuntime.Dynamic(CustomPropSymbol('ma', 'quality-assessment.qmean', Type.Num),
|
||||
ctx => {
|
||||
const { unit, element } = ctx.element;
|
||||
if (!Unit.isAtomic(unit)) return -1;
|
||||
const qualityAssessment = QualityAssessmentProvider.get(unit.model).value;
|
||||
return qualityAssessment?.qmean?.get(unit.model.atomicHierarchy.residueAtomSegments.index[element]) ?? -1;
|
||||
}
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export const QualityAssessmentParams = { };
|
||||
export type QualityAssessmentParams = typeof QualityAssessmentParams
|
||||
export type QualityAssessmentProps = PD.Values<QualityAssessmentParams>
|
||||
|
||||
export const QualityAssessmentProvider: CustomModelProperty.Provider<QualityAssessmentParams, QualityAssessment> = CustomModelProperty.createProvider({
|
||||
label: 'QualityAssessment',
|
||||
descriptor: CustomPropertyDescriptor({
|
||||
name: 'ma_quality_assessment',
|
||||
symbols: QualityAssessment.symbols
|
||||
}),
|
||||
type: 'static',
|
||||
defaultParams: QualityAssessmentParams,
|
||||
getParams: (data: Model) => QualityAssessmentParams,
|
||||
isApplicable: (data: Model) => QualityAssessment.isApplicable(data),
|
||||
obtain: async (ctx: CustomProperty.Context, data: Model, props: Partial<QualityAssessmentProps>) => {
|
||||
const p = { ...PD.getDefaultValues(QualityAssessmentParams), ...props };
|
||||
return await QualityAssessment.obtain(ctx, data, p);
|
||||
}
|
||||
});
|
||||
@@ -31,7 +31,7 @@ export class Mp4Controls extends PluginComponent {
|
||||
canApply: this.ev.behavior<PluginStateAnimation.CanApply>({ canApply: false }),
|
||||
info: this.ev.behavior<Mp4AnimationInfo>({ width: 0, height: 0 }),
|
||||
params: this.ev.behavior<PD.Values<typeof Mp4AnimationParams>>(PD.getDefaultValues(Mp4AnimationParams))
|
||||
}
|
||||
};
|
||||
|
||||
setCurrent(name?: string) {
|
||||
const anim = this.animations.find(a => a.name === name);
|
||||
@@ -125,17 +125,20 @@ export class Mp4Controls extends PluginComponent {
|
||||
this.subscribe(this.plugin.canvas3d?.resized!, () => this.syncInfo());
|
||||
this.subscribe(this.plugin.helpers.viewportScreenshot?.events.previewed!, () => this.syncInfo());
|
||||
|
||||
this.subscribe(this.plugin.behaviors.state.isBusy, b => {
|
||||
const anim = this.current;
|
||||
if (!b && anim) {
|
||||
this.behaviors.canApply.next(anim.anim.canApply?.(this.plugin) ?? { canApply: true });
|
||||
}
|
||||
});
|
||||
this.subscribe(this.plugin.behaviors.state.isBusy, b => this.updateCanApply(b));
|
||||
this.subscribe(this.plugin.managers.snapshot.events.changed, b => this.updateCanApply(b));
|
||||
|
||||
this.sync();
|
||||
this.syncInfo();
|
||||
}
|
||||
|
||||
private updateCanApply(b?: any) {
|
||||
const anim = this.current;
|
||||
if (!b && anim) {
|
||||
this.behaviors.canApply.next(anim.anim.canApply?.(this.plugin) ?? { canApply: true });
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private plugin: PluginContext) {
|
||||
super();
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ export class Mp4EncoderUI extends CollapsableControls<{}, State> {
|
||||
|
||||
save = () => {
|
||||
download(new Blob([this.state.data!.movie]), this.state.data!.filename);
|
||||
}
|
||||
};
|
||||
|
||||
generate = async () => {
|
||||
try {
|
||||
@@ -119,5 +119,5 @@ export class Mp4EncoderUI extends CollapsableControls<{}, State> {
|
||||
console.error(e);
|
||||
this.setState({ busy: false });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -21,7 +21,7 @@ export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: bo
|
||||
},
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
|
||||
|
||||
private provider = StructureQualityReportProvider
|
||||
private provider = StructureQualityReportProvider;
|
||||
|
||||
private labelPDBeValidation = {
|
||||
label: (loci: Loci): string | undefined => {
|
||||
@@ -42,7 +42,7 @@ export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: bo
|
||||
default: return void 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
register(): void {
|
||||
this.ctx.customModelProperties.register(this.provider, this.params.autoAttach);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace StructureQualityReport {
|
||||
}
|
||||
|
||||
export function isApplicable(model?: Model): boolean {
|
||||
return !!model && Model.isFromPdbArchive(model);
|
||||
return !!model && Model.hasPdbId(model);
|
||||
}
|
||||
|
||||
export const Schema = {
|
||||
|
||||
@@ -27,7 +27,7 @@ export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean
|
||||
description: 'Assembly Symmetry data calculated with BioJava, obtained via RCSB PDB.'
|
||||
},
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean }> {
|
||||
private provider = AssemblySymmetryProvider
|
||||
private provider = AssemblySymmetryProvider;
|
||||
|
||||
register(): void {
|
||||
this.ctx.state.data.actions.add(InitAssemblySymmetry3D);
|
||||
|
||||
@@ -53,7 +53,7 @@ export namespace AssemblySymmetry {
|
||||
export function isApplicable(structure?: Structure): boolean {
|
||||
return (
|
||||
!!structure && structure.models.length === 1 &&
|
||||
Model.isFromPdbArchive(structure.models[0]) &&
|
||||
Model.hasPdbId(structure.models[0]) &&
|
||||
isBiologicalAssembly(structure)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy
|
||||
|
||||
paramsOnChange = (options: AssemblySymmetryProps) => {
|
||||
this.updateAssemblySymmetry(options);
|
||||
}
|
||||
};
|
||||
|
||||
get hasAssemblySymmetry3D() {
|
||||
return !this.pivot.cell.parent || !!StateSelection.findTagInSubtree(this.pivot.cell.parent.tree, this.pivot.cell.transform.ref, AssemblySymmetry.Tag.Representation);
|
||||
|
||||
@@ -30,7 +30,7 @@ export const RCSBValidationReport = PluginBehavior.create<{ autoAttach: boolean,
|
||||
description: 'Data from wwPDB Validation Report, obtained via RCSB PDB.'
|
||||
},
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
|
||||
private provider = ValidationReportProvider
|
||||
private provider = ValidationReportProvider;
|
||||
|
||||
private labelProvider = {
|
||||
label: (loci: Loci): string | undefined => {
|
||||
@@ -41,7 +41,7 @@ export const RCSBValidationReport = PluginBehavior.create<{ autoAttach: boolean,
|
||||
randomCoilIndexLabel(loci)
|
||||
].filter(l => !!l).join('</br>');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
register(): void {
|
||||
DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor);
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace ValidationReport {
|
||||
}
|
||||
|
||||
export function isApplicable(model?: Model): boolean {
|
||||
return !!model && Model.isFromPdbArchive(model);
|
||||
return !!model && Model.hasPdbId(model);
|
||||
}
|
||||
|
||||
export function fromXml(xml: XMLDocument, model: Model): ValidationReport {
|
||||
|
||||
@@ -37,7 +37,7 @@ class Camera implements ICamera {
|
||||
readonly projectionView: Mat4 = Mat4.identity();
|
||||
readonly inverseProjectionView: Mat4 = Mat4.identity();
|
||||
|
||||
private pixelScale: number
|
||||
private pixelScale: number;
|
||||
get pixelRatio() {
|
||||
const dpr = (typeof window !== 'undefined') ? window.devicePixelRatio : 1;
|
||||
return dpr * this.pixelScale;
|
||||
@@ -47,11 +47,11 @@ class Camera implements ICamera {
|
||||
readonly state: Readonly<Camera.Snapshot> = Camera.createDefaultSnapshot();
|
||||
readonly viewOffset = Camera.ViewOffset();
|
||||
|
||||
near = 1
|
||||
far = 10000
|
||||
fogNear = 5000
|
||||
fogFar = 10000
|
||||
zoom = 1
|
||||
near = 1;
|
||||
far = 10000;
|
||||
fogNear = 5000;
|
||||
fogFar = 10000;
|
||||
zoom = 1;
|
||||
|
||||
readonly transition: CameraTransitionManager = new CameraTransitionManager(this);
|
||||
readonly stateChanged = new BehaviorSubject<Partial<Camera.Snapshot>>(this.state);
|
||||
|
||||
@@ -33,7 +33,7 @@ class StereoCamera {
|
||||
return this.parent.viewOffset;
|
||||
}
|
||||
|
||||
private props: StereoCameraProps
|
||||
private props: StereoCameraProps;
|
||||
|
||||
constructor(private parent: Camera, props: Partial<StereoCameraProps> = {}) {
|
||||
this.props = { ...DefaultStereoCameraProps, ...props };
|
||||
|
||||
@@ -395,7 +395,11 @@ namespace Canvas3D {
|
||||
}
|
||||
|
||||
if (MultiSamplePass.isEnabled(p.multiSample)) {
|
||||
multiSampleHelper.render(renderer, cam, scene, helper, true, p.transparentBackground, p);
|
||||
if (!cameraChanged) {
|
||||
while (!multiSampleHelper.render(renderer, cam, scene, helper, true, p.transparentBackground, p));
|
||||
} else {
|
||||
multiSampleHelper.render(renderer, cam, scene, helper, true, p.transparentBackground, p);
|
||||
}
|
||||
} else {
|
||||
passes.draw.render(renderer, cam, scene, helper, true, p.transparentBackground, p.postprocessing, p.marking);
|
||||
}
|
||||
@@ -514,7 +518,7 @@ namespace Canvas3D {
|
||||
|
||||
if (camera.transition.inTransition || nextCameraResetSnapshot) return false;
|
||||
|
||||
let cameraSphereOverlapsNone = true;
|
||||
let cameraSphereOverlapsNone = true, isEmpty = true;
|
||||
Sphere3D.set(cameraSphere, camera.state.target, camera.state.radius);
|
||||
|
||||
// check if any renderable has moved outside of the old bounding sphere
|
||||
@@ -525,12 +529,13 @@ namespace Canvas3D {
|
||||
const b = r.values.boundingSphere.ref.value;
|
||||
if (!b.radius) continue;
|
||||
|
||||
isEmpty = false;
|
||||
const cameraDist = Vec3.distance(cameraSphere.center, b.center);
|
||||
if ((cameraDist > cameraSphere.radius || cameraDist > b.radius || b.radius > camera.state.radiusMax) && !Sphere3D.includes(oldBoundingSphereVisible, b)) return true;
|
||||
if (Sphere3D.overlaps(cameraSphere, b)) cameraSphereOverlapsNone = false;
|
||||
}
|
||||
|
||||
return cameraSphereOverlapsNone;
|
||||
return cameraSphereOverlapsNone || (!isEmpty && cameraSphere.radius <= 0.1);
|
||||
}
|
||||
|
||||
const sceneCommitTimeoutMs = 250;
|
||||
|
||||
@@ -31,14 +31,14 @@ export type DebugHelperProps = PD.Values<DebugHelperParams>
|
||||
type BoundingSphereData = { boundingSphere: Sphere3D, renderObject: GraphicsRenderObject, mesh: Mesh }
|
||||
|
||||
export class BoundingSphereHelper {
|
||||
readonly scene: Scene
|
||||
readonly scene: Scene;
|
||||
|
||||
private readonly parent: Scene
|
||||
private _props: DebugHelperProps
|
||||
private objectsData = new Map<GraphicsRenderObject, BoundingSphereData>()
|
||||
private instancesData = new Map<GraphicsRenderObject, BoundingSphereData>()
|
||||
private sceneData: BoundingSphereData | undefined
|
||||
private visibleSceneData: BoundingSphereData | undefined
|
||||
private readonly parent: Scene;
|
||||
private _props: DebugHelperProps;
|
||||
private objectsData = new Map<GraphicsRenderObject, BoundingSphereData>();
|
||||
private instancesData = new Map<GraphicsRenderObject, BoundingSphereData>();
|
||||
private sceneData: BoundingSphereData | undefined;
|
||||
private visibleSceneData: BoundingSphereData | undefined;
|
||||
|
||||
constructor(ctx: WebGLContext, parent: Scene, props: Partial<DebugHelperProps>) {
|
||||
this.scene = Scene.create(ctx);
|
||||
|
||||
@@ -49,13 +49,13 @@ export type CameraHelperParams = typeof CameraHelperParams
|
||||
export type CameraHelperProps = PD.Values<CameraHelperParams>
|
||||
|
||||
export class CameraHelper {
|
||||
scene: Scene
|
||||
camera: Camera
|
||||
scene: Scene;
|
||||
camera: Camera;
|
||||
props: CameraHelperProps = {
|
||||
axes: { name: 'off', params: {} }
|
||||
}
|
||||
};
|
||||
|
||||
private renderObject: GraphicsRenderObject | undefined
|
||||
private renderObject: GraphicsRenderObject | undefined;
|
||||
|
||||
constructor(private webgl: WebGLContext, props: Partial<CameraHelperProps> = {}) {
|
||||
this.scene = Scene.create(webgl);
|
||||
@@ -109,7 +109,7 @@ export class CameraHelper {
|
||||
if (apply(Interval.ofSingleton(idx))) changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
};
|
||||
|
||||
mark(loci: Loci, action: MarkerAction) {
|
||||
if (!MarkerActions.is(MarkerActions.Highlighting, action)) return false;
|
||||
|
||||
@@ -47,12 +47,12 @@ export type HandleHelperParams = typeof HandleHelperParams
|
||||
export type HandleHelperProps = PD.Values<HandleHelperParams>
|
||||
|
||||
export class HandleHelper {
|
||||
scene: Scene
|
||||
scene: Scene;
|
||||
props: HandleHelperProps = {
|
||||
handle: { name: 'off', params: {} }
|
||||
}
|
||||
};
|
||||
|
||||
private renderObject: GraphicsRenderObject | undefined
|
||||
private renderObject: GraphicsRenderObject | undefined;
|
||||
|
||||
private _transform = Mat4();
|
||||
getBoundingSphere(out: Sphere3D, instanceId: number) {
|
||||
@@ -117,7 +117,7 @@ export class HandleHelper {
|
||||
if (apply(Interval.ofSingleton(idx))) changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
};
|
||||
|
||||
mark(loci: Loci, action: MarkerAction) {
|
||||
if (!MarkerActions.is(MarkerActions.Highlighting, action)) return false;
|
||||
|
||||
@@ -23,9 +23,9 @@ export type HelperProps = PD.Values<typeof HelperParams>
|
||||
|
||||
|
||||
export class Helper {
|
||||
readonly debug: BoundingSphereHelper
|
||||
readonly camera: CameraHelper
|
||||
readonly handle: HandleHelper
|
||||
readonly debug: BoundingSphereHelper;
|
||||
readonly camera: CameraHelper;
|
||||
readonly handle: HandleHelper;
|
||||
|
||||
constructor(webgl: WebGLContext, scene: Scene, props: Partial<HelperProps> = {}) {
|
||||
const p = { ...DefaultHelperProps, ...props };
|
||||
|
||||
@@ -54,27 +54,27 @@ function getDepthMergeRenderable(ctx: WebGLContext, depthTexturePrimitives: Text
|
||||
}
|
||||
|
||||
export class DrawPass {
|
||||
private readonly drawTarget: RenderTarget
|
||||
private readonly drawTarget: RenderTarget;
|
||||
|
||||
readonly colorTarget: RenderTarget
|
||||
readonly depthTexture: Texture
|
||||
readonly depthTexturePrimitives: Texture
|
||||
readonly colorTarget: RenderTarget;
|
||||
readonly depthTexture: Texture;
|
||||
readonly depthTexturePrimitives: Texture;
|
||||
|
||||
readonly packedDepth: boolean
|
||||
readonly packedDepth: boolean;
|
||||
|
||||
private depthTarget: RenderTarget
|
||||
private depthTargetPrimitives: RenderTarget | null
|
||||
private depthTargetVolumes: RenderTarget | null
|
||||
private depthTextureVolumes: Texture
|
||||
private depthMerge: DepthMergeRenderable
|
||||
private depthTarget: RenderTarget;
|
||||
private depthTargetPrimitives: RenderTarget | null;
|
||||
private depthTargetVolumes: RenderTarget | null;
|
||||
private depthTextureVolumes: Texture;
|
||||
private depthMerge: DepthMergeRenderable;
|
||||
|
||||
private copyFboTarget: CopyRenderable
|
||||
private copyFboPostprocessing: CopyRenderable
|
||||
private copyFboTarget: CopyRenderable;
|
||||
private copyFboPostprocessing: CopyRenderable;
|
||||
|
||||
private wboit: WboitPass | undefined
|
||||
private readonly marking: MarkingPass
|
||||
readonly postprocessing: PostprocessingPass
|
||||
private readonly antialiasing: AntialiasingPass
|
||||
private wboit: WboitPass | undefined;
|
||||
private readonly marking: MarkingPass;
|
||||
readonly postprocessing: PostprocessingPass;
|
||||
private readonly antialiasing: AntialiasingPass;
|
||||
|
||||
get wboitEnabled() {
|
||||
return !!this.wboit?.supported;
|
||||
|
||||
@@ -28,7 +28,7 @@ export const FxaaParams = {
|
||||
export type FxaaProps = PD.Values<typeof FxaaParams>
|
||||
|
||||
export class FxaaPass {
|
||||
private readonly renderable: FxaaRenderable
|
||||
private readonly renderable: FxaaRenderable;
|
||||
|
||||
constructor(private webgl: WebGLContext, input: Texture) {
|
||||
this.renderable = getFxaaRenderable(webgl, input);
|
||||
|
||||
@@ -30,19 +30,19 @@ export const ImageParams = {
|
||||
export type ImageProps = PD.Values<typeof ImageParams>
|
||||
|
||||
export class ImagePass {
|
||||
private _width = 0
|
||||
private _height = 0
|
||||
private _camera = new Camera()
|
||||
private _width = 0;
|
||||
private _height = 0;
|
||||
private _camera = new Camera();
|
||||
|
||||
readonly props: ImageProps
|
||||
readonly props: ImageProps;
|
||||
|
||||
private _colorTarget: RenderTarget
|
||||
private _colorTarget: RenderTarget;
|
||||
get colorTarget() { return this._colorTarget; }
|
||||
|
||||
private readonly drawPass: DrawPass
|
||||
private readonly multiSamplePass: MultiSamplePass
|
||||
private readonly multiSampleHelper: MultiSampleHelper
|
||||
private readonly helper: Helper
|
||||
private readonly drawPass: DrawPass;
|
||||
private readonly multiSamplePass: MultiSamplePass;
|
||||
private readonly multiSampleHelper: MultiSampleHelper;
|
||||
private readonly helper: Helper;
|
||||
|
||||
get width() { return this._width; }
|
||||
get height() { return this._height; }
|
||||
|
||||
@@ -36,12 +36,12 @@ export class MarkingPass {
|
||||
return props.enabled;
|
||||
}
|
||||
|
||||
readonly depthTarget: RenderTarget
|
||||
readonly maskTarget: RenderTarget
|
||||
private readonly edgesTarget: RenderTarget
|
||||
readonly depthTarget: RenderTarget;
|
||||
readonly maskTarget: RenderTarget;
|
||||
private readonly edgesTarget: RenderTarget;
|
||||
|
||||
private readonly edge: EdgeRenderable
|
||||
private readonly overlay: OverlayRenderable
|
||||
private readonly edge: EdgeRenderable;
|
||||
private readonly overlay: OverlayRenderable;
|
||||
|
||||
constructor(private webgl: WebGLContext, width: number, height: number) {
|
||||
this.depthTarget = webgl.createRenderTarget(width, height);
|
||||
|
||||
@@ -50,8 +50,8 @@ function getComposeRenderable(ctx: WebGLContext, colorTexture: Texture): Compose
|
||||
}
|
||||
|
||||
export const MultiSampleParams = {
|
||||
mode: PD.Select('off', [['off', 'Off'], ['on', 'On'], ['temporal', 'Temporal']]),
|
||||
sampleLevel: PD.Numeric(2, { min: 0, max: 5, step: 1 }),
|
||||
mode: PD.Select('temporal', [['off', 'Off'], ['on', 'On'], ['temporal', 'Temporal']]),
|
||||
sampleLevel: PD.Numeric(2, { min: 0, max: 5, step: 1 }, { description: 'Take level^2 samples.' }),
|
||||
};
|
||||
export type MultiSampleProps = PD.Values<typeof MultiSampleParams>
|
||||
|
||||
@@ -66,11 +66,11 @@ export class MultiSamplePass {
|
||||
return props.mode !== 'off';
|
||||
}
|
||||
|
||||
colorTarget: RenderTarget
|
||||
colorTarget: RenderTarget;
|
||||
|
||||
private composeTarget: RenderTarget
|
||||
private holdTarget: RenderTarget
|
||||
private compose: ComposeRenderable
|
||||
private composeTarget: RenderTarget;
|
||||
private holdTarget: RenderTarget;
|
||||
private compose: ComposeRenderable;
|
||||
|
||||
constructor(private webgl: WebGLContext, private drawPass: DrawPass) {
|
||||
const { colorBufferFloat, textureFloat, colorBufferHalfFloat, textureHalfFloat } = webgl.extensions;
|
||||
@@ -317,15 +317,17 @@ JitterVectors.forEach(offsetList => {
|
||||
});
|
||||
|
||||
export class MultiSampleHelper {
|
||||
private sampleIndex = -2
|
||||
private sampleIndex = -2;
|
||||
|
||||
update(changed: boolean, props: MultiSampleProps) {
|
||||
if (changed) this.sampleIndex = -1;
|
||||
return props.mode === 'temporal' ? this.sampleIndex !== -2 : false;
|
||||
}
|
||||
|
||||
/** Return `true` while more samples are needed */
|
||||
render(renderer: Renderer, camera: Camera | StereoCamera, scene: Scene, helper: Helper, toDrawingBuffer: boolean, transparentBackground: boolean, props: Props) {
|
||||
this.sampleIndex = this.multiSamplePass.render(this.sampleIndex, renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
|
||||
return this.sampleIndex < 0;
|
||||
}
|
||||
|
||||
constructor(private multiSamplePass: MultiSamplePass) {
|
||||
|
||||
@@ -10,9 +10,9 @@ import { MultiSamplePass } from './multi-sample';
|
||||
import { WebGLContext } from '../../mol-gl/webgl/context';
|
||||
|
||||
export class Passes {
|
||||
readonly draw: DrawPass
|
||||
readonly pick: PickPass
|
||||
readonly multiSample: MultiSamplePass
|
||||
readonly draw: DrawPass;
|
||||
readonly pick: PickPass;
|
||||
readonly multiSample: MultiSamplePass;
|
||||
|
||||
constructor(private webgl: WebGLContext, attribs: Partial<{ pickScale: number, enableWboit: boolean }> = {}) {
|
||||
const { gl } = webgl;
|
||||
|
||||
@@ -25,13 +25,13 @@ const NullId = Math.pow(2, 24) - 2;
|
||||
export type PickData = { id: PickingId, position: Vec3 }
|
||||
|
||||
export class PickPass {
|
||||
readonly objectPickTarget: RenderTarget
|
||||
readonly instancePickTarget: RenderTarget
|
||||
readonly groupPickTarget: RenderTarget
|
||||
readonly depthPickTarget: RenderTarget
|
||||
readonly objectPickTarget: RenderTarget;
|
||||
readonly instancePickTarget: RenderTarget;
|
||||
readonly groupPickTarget: RenderTarget;
|
||||
readonly depthPickTarget: RenderTarget;
|
||||
|
||||
private pickWidth: number
|
||||
private pickHeight: number
|
||||
private pickWidth: number;
|
||||
private pickHeight: number;
|
||||
|
||||
constructor(private webgl: WebGLContext, private drawPass: DrawPass, readonly pickBaseScale: number) {
|
||||
const pickScale = pickBaseScale / webgl.pixelRatio;
|
||||
@@ -97,23 +97,23 @@ export class PickPass {
|
||||
}
|
||||
|
||||
export class PickHelper {
|
||||
dirty = true
|
||||
dirty = true;
|
||||
|
||||
private objectBuffer: Uint8Array
|
||||
private instanceBuffer: Uint8Array
|
||||
private groupBuffer: Uint8Array
|
||||
private depthBuffer: Uint8Array
|
||||
private objectBuffer: Uint8Array;
|
||||
private instanceBuffer: Uint8Array;
|
||||
private groupBuffer: Uint8Array;
|
||||
private depthBuffer: Uint8Array;
|
||||
|
||||
private viewport = Viewport()
|
||||
private viewport = Viewport();
|
||||
|
||||
private pickScale: number
|
||||
private pickX: number
|
||||
private pickY: number
|
||||
private pickWidth: number
|
||||
private pickHeight: number
|
||||
private halfPickWidth: number
|
||||
private pickScale: number;
|
||||
private pickX: number;
|
||||
private pickY: number;
|
||||
private pickWidth: number;
|
||||
private pickHeight: number;
|
||||
private halfPickWidth: number;
|
||||
|
||||
private spiral: [number, number][]
|
||||
private spiral: [number, number][];
|
||||
|
||||
private setupBuffers() {
|
||||
const bufferSize = this.pickWidth * this.pickHeight * 4;
|
||||
|
||||
@@ -193,6 +193,7 @@ const PostprocessingSchema = {
|
||||
uFogNear: UniformSpec('f'),
|
||||
uFogFar: UniformSpec('f'),
|
||||
uFogColor: UniformSpec('v3'),
|
||||
uOutlineColor: UniformSpec('v3'),
|
||||
uTransparentBackground: UniformSpec('b'),
|
||||
|
||||
uMaxPossibleViewZDiff: UniformSpec('f'),
|
||||
@@ -220,6 +221,7 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d
|
||||
uFogNear: ValueCell.create(10000),
|
||||
uFogFar: ValueCell.create(10000),
|
||||
uFogColor: ValueCell.create(Vec3.create(1, 1, 1)),
|
||||
uOutlineColor: ValueCell.create(Vec3.create(0, 0, 0)),
|
||||
uTransparentBackground: ValueCell.create(false),
|
||||
|
||||
uMaxPossibleViewZDiff: ValueCell.create(0.5),
|
||||
@@ -252,6 +254,7 @@ export const PostprocessingParams = {
|
||||
on: PD.Group({
|
||||
scale: PD.Numeric(1, { min: 1, max: 5, step: 1 }),
|
||||
threshold: PD.Numeric(0.33, { min: 0.01, max: 1, step: 0.01 }),
|
||||
color: PD.Color(Color(0x000000)),
|
||||
}),
|
||||
off: PD.Group({})
|
||||
}, { cycle: true, description: 'Draw outline around 3D objects' }),
|
||||
@@ -268,29 +271,29 @@ export class PostprocessingPass {
|
||||
return props.occlusion.name === 'on' || props.outline.name === 'on';
|
||||
}
|
||||
|
||||
readonly target: RenderTarget
|
||||
readonly target: RenderTarget;
|
||||
|
||||
private readonly outlinesTarget: RenderTarget
|
||||
private readonly outlinesRenderable: OutlinesRenderable
|
||||
private readonly outlinesTarget: RenderTarget;
|
||||
private readonly outlinesRenderable: OutlinesRenderable;
|
||||
|
||||
private readonly randomHemisphereVector: Vec3[]
|
||||
private readonly ssaoFramebuffer: Framebuffer
|
||||
private readonly ssaoBlurFirstPassFramebuffer: Framebuffer
|
||||
private readonly ssaoBlurSecondPassFramebuffer: Framebuffer
|
||||
private readonly randomHemisphereVector: Vec3[];
|
||||
private readonly ssaoFramebuffer: Framebuffer;
|
||||
private readonly ssaoBlurFirstPassFramebuffer: Framebuffer;
|
||||
private readonly ssaoBlurSecondPassFramebuffer: Framebuffer;
|
||||
|
||||
private readonly ssaoDepthTexture: Texture
|
||||
private readonly ssaoDepthBlurProxyTexture: Texture
|
||||
private readonly ssaoDepthTexture: Texture;
|
||||
private readonly ssaoDepthBlurProxyTexture: Texture;
|
||||
|
||||
private readonly ssaoRenderable: SsaoRenderable
|
||||
private readonly ssaoBlurFirstPassRenderable: SsaoBlurRenderable
|
||||
private readonly ssaoBlurSecondPassRenderable: SsaoBlurRenderable
|
||||
private readonly ssaoRenderable: SsaoRenderable;
|
||||
private readonly ssaoBlurFirstPassRenderable: SsaoBlurRenderable;
|
||||
private readonly ssaoBlurSecondPassRenderable: SsaoBlurRenderable;
|
||||
|
||||
private nSamples: number
|
||||
private blurKernelSize: number
|
||||
private nSamples: number;
|
||||
private blurKernelSize: number;
|
||||
|
||||
private readonly renderable: PostprocessingRenderable
|
||||
private readonly renderable: PostprocessingRenderable;
|
||||
|
||||
private ssaoScale: number
|
||||
private ssaoScale: number;
|
||||
private calcSsaoScale() {
|
||||
// downscale ssao for high pixel-ratios
|
||||
return Math.min(1, 1 / this.webgl.pixelRatio);
|
||||
@@ -446,6 +449,8 @@ export class PostprocessingPass {
|
||||
ValueCell.updateIfChanged(this.outlinesRenderable.values.uFar, camera.far);
|
||||
ValueCell.updateIfChanged(this.outlinesRenderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff);
|
||||
|
||||
ValueCell.update(this.renderable.values.uOutlineColor, Color.toVec3Normalized(this.renderable.values.uOutlineColor.ref.value, props.outline.params.color));
|
||||
|
||||
ValueCell.updateIfChanged(this.renderable.values.uMaxPossibleViewZDiff, maxPossibleViewZDiff);
|
||||
if (this.renderable.values.dOutlineScale.ref.value !== outlineScale) { needsUpdateMain = true; }
|
||||
ValueCell.updateIfChanged(this.renderable.values.dOutlineScale, outlineScale);
|
||||
@@ -538,9 +543,9 @@ export class AntialiasingPass {
|
||||
return props.antialiasing.name !== 'off';
|
||||
}
|
||||
|
||||
readonly target: RenderTarget
|
||||
private readonly fxaa: FxaaPass
|
||||
private readonly smaa: SmaaPass
|
||||
readonly target: RenderTarget;
|
||||
private readonly fxaa: FxaaPass;
|
||||
private readonly smaa: SmaaPass;
|
||||
|
||||
constructor(webgl: WebGLContext, private drawPass: DrawPass) {
|
||||
const { colorTarget } = drawPass;
|
||||
|
||||
@@ -31,12 +31,12 @@ export const SmaaParams = {
|
||||
export type SmaaProps = PD.Values<typeof SmaaParams>
|
||||
|
||||
export class SmaaPass {
|
||||
private readonly edgesTarget: RenderTarget
|
||||
private readonly weightsTarget: RenderTarget
|
||||
private readonly edgesTarget: RenderTarget;
|
||||
private readonly weightsTarget: RenderTarget;
|
||||
|
||||
private readonly edgesRenderable: EdgesRenderable
|
||||
private readonly weightsRenderable: WeightsRenderable
|
||||
private readonly blendRenderable: BlendRenderable
|
||||
private readonly edgesRenderable: EdgesRenderable;
|
||||
private readonly weightsRenderable: WeightsRenderable;
|
||||
private readonly blendRenderable: BlendRenderable;
|
||||
|
||||
private _supported = false;
|
||||
get supported() {
|
||||
|
||||
@@ -45,11 +45,11 @@ function getEvaluateWboitRenderable(ctx: WebGLContext, wboitATexture: Texture, w
|
||||
//
|
||||
|
||||
export class WboitPass {
|
||||
private readonly renderable: EvaluateWboitRenderable
|
||||
private readonly renderable: EvaluateWboitRenderable;
|
||||
|
||||
private readonly framebuffer: Framebuffer
|
||||
private readonly textureA: Texture
|
||||
private readonly textureB: Texture
|
||||
private readonly framebuffer: Framebuffer;
|
||||
private readonly textureA: Texture;
|
||||
private readonly textureB: Texture;
|
||||
|
||||
private _supported = false;
|
||||
get supported() {
|
||||
|
||||
@@ -87,9 +87,9 @@ namespace SortedRanges {
|
||||
}
|
||||
|
||||
export class Iterator<T extends number = number, I extends number = number> implements _Iterator<Segmentation.Segment<I>> {
|
||||
private value: Segmentation.Segment<I> = { index: 0 as I, start: 0 as T, end: 0 as T }
|
||||
private value: Segmentation.Segment<I> = { index: 0 as I, start: 0 as T, end: 0 as T };
|
||||
|
||||
private curIndex = 0
|
||||
private curIndex = 0;
|
||||
|
||||
hasNext: boolean = false;
|
||||
|
||||
|
||||
@@ -28,11 +28,11 @@ function nextIndex(n: number) {
|
||||
};
|
||||
|
||||
export class CombinationIterator<T> implements Iterator<ReadonlyArray<T>> {
|
||||
private value: T[]
|
||||
private index: number
|
||||
private maxIndex: number
|
||||
private value: T[];
|
||||
private index: number;
|
||||
private maxIndex: number;
|
||||
|
||||
size: number
|
||||
size: number;
|
||||
hasNext: boolean = false;
|
||||
|
||||
move() {
|
||||
|
||||
@@ -9,10 +9,10 @@ import { OrderedSet, Interval, Segmentation } from '../int';
|
||||
|
||||
/** Emits a segment of length one for each element in the interval that is also in the set */
|
||||
export class IntervalIterator<I extends number = number> implements Iterator<Segmentation.Segment<I>> {
|
||||
private value: Segmentation.Segment<I> = { index: 0 as I, start: 0, end: 0 }
|
||||
private value: Segmentation.Segment<I> = { index: 0 as I, start: 0, end: 0 };
|
||||
|
||||
private curIndex = 0
|
||||
private maxIndex = 0
|
||||
private curIndex = 0;
|
||||
private maxIndex = 0;
|
||||
|
||||
hasNext: boolean = false;
|
||||
|
||||
|
||||
@@ -97,24 +97,24 @@ export namespace BaseGeometry {
|
||||
}
|
||||
|
||||
export function createValues(props: PD.Values<Params>, counts: Counts) {
|
||||
const { metalness, roughness } = Material.toObjectNormalized(props.material);
|
||||
return {
|
||||
alpha: ValueCell.create(props.alpha),
|
||||
uAlpha: ValueCell.create(props.alpha),
|
||||
uVertexCount: ValueCell.create(counts.vertexCount),
|
||||
uGroupCount: ValueCell.create(counts.groupCount),
|
||||
drawCount: ValueCell.create(counts.drawCount),
|
||||
uMetalness: ValueCell.create(metalness),
|
||||
uRoughness: ValueCell.create(roughness),
|
||||
uMetalness: ValueCell.create(props.material.metalness),
|
||||
uRoughness: ValueCell.create(props.material.roughness),
|
||||
uBumpiness: ValueCell.create(props.material.bumpiness),
|
||||
dLightCount: ValueCell.create(1),
|
||||
};
|
||||
}
|
||||
|
||||
export function updateValues(values: BaseValues, props: PD.Values<Params>) {
|
||||
const { metalness, roughness } = Material.toObjectNormalized(props.material);
|
||||
ValueCell.updateIfChanged(values.alpha, props.alpha); // `uAlpha` is set in renderable.render
|
||||
ValueCell.updateIfChanged(values.uMetalness, metalness);
|
||||
ValueCell.updateIfChanged(values.uRoughness, roughness);
|
||||
ValueCell.updateIfChanged(values.uMetalness, props.material.metalness);
|
||||
ValueCell.updateIfChanged(values.uRoughness, props.material.roughness);
|
||||
ValueCell.updateIfChanged(values.uBumpiness, props.material.bumpiness);
|
||||
}
|
||||
|
||||
export function createRenderableState(props: Partial<PD.Values<Params>> = {}): RenderableState {
|
||||
|
||||
@@ -157,6 +157,8 @@ export namespace Cylinders {
|
||||
doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
export type Params = typeof Params
|
||||
|
||||
@@ -237,6 +239,8 @@ export namespace Cylinders {
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -252,6 +256,8 @@ export namespace Cylinders {
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
function updateBoundingSphere(values: CylindersValues, cylinders: Cylinders) {
|
||||
|
||||
@@ -376,7 +376,7 @@ export function applyMeshSubstanceSmoothing(values: MeshValues, resolution: numb
|
||||
colorType: values.dSubstanceType.ref.value,
|
||||
boundingSphere: values.boundingSphere.ref.value,
|
||||
invariantBoundingSphere: values.invariantBoundingSphere.ref.value,
|
||||
itemSize: 3
|
||||
itemSize: 4
|
||||
}, resolution, stride, webgl, colorTexture);
|
||||
if (smoothingData.kind === 'volume') {
|
||||
ValueCell.updateIfChanged(values.dSubstanceType, smoothingData.type);
|
||||
|
||||
@@ -625,6 +625,8 @@ export namespace Mesh {
|
||||
flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
export type Params = typeof Params
|
||||
|
||||
@@ -696,6 +698,8 @@ export namespace Mesh {
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
|
||||
meta: ValueCell.create(mesh.meta),
|
||||
};
|
||||
@@ -714,6 +718,8 @@ export namespace Mesh {
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
function updateBoundingSphere(values: MeshValues, mesh: Mesh) {
|
||||
|
||||
@@ -129,6 +129,8 @@ export namespace Spheres {
|
||||
doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
export type Params = typeof Params
|
||||
|
||||
@@ -204,6 +206,8 @@ export namespace Spheres {
|
||||
dDoubleSided: ValueCell.create(props.doubleSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -219,6 +223,8 @@ export namespace Spheres {
|
||||
ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
function updateBoundingSphere(values: SpheresValues, spheres: Spheres) {
|
||||
|
||||
@@ -23,14 +23,14 @@ export type SubstanceData = {
|
||||
|
||||
export function applySubstanceMaterial(array: Uint8Array, start: number, end: number, material: Material) {
|
||||
for (let i = start; i < end; ++i) {
|
||||
Material.toArray(material, array, i * 3);
|
||||
array[i * 3 + 2] = 255;
|
||||
Material.toArray(material, array, i * 4);
|
||||
array[i * 4 + 3] = 255;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function clearSubstance(array: Uint8Array, start: number, end: number) {
|
||||
array.fill(0, start * 3, end * 3);
|
||||
array.fill(0, start * 4, end * 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,35 +39,35 @@ export type FontAtlasMap = {
|
||||
}
|
||||
|
||||
export class FontAtlas {
|
||||
readonly props: Readonly<FontAtlasProps>
|
||||
readonly mapped: { [k: string]: FontAtlasMap } = {}
|
||||
readonly placeholder: FontAtlasMap
|
||||
readonly texture: TextureImage<Uint8Array>
|
||||
readonly props: Readonly<FontAtlasProps>;
|
||||
readonly mapped: { [k: string]: FontAtlasMap } = {};
|
||||
readonly placeholder: FontAtlasMap;
|
||||
readonly texture: TextureImage<Uint8Array>;
|
||||
|
||||
private scratchW = 0
|
||||
private scratchH = 0
|
||||
private currentX = 0
|
||||
private currentY = 0
|
||||
private readonly scratchData: Uint8Array
|
||||
private scratchW = 0;
|
||||
private scratchH = 0;
|
||||
private currentX = 0;
|
||||
private currentY = 0;
|
||||
private readonly scratchData: Uint8Array;
|
||||
|
||||
private readonly cutoff = 0.5
|
||||
readonly buffer: number
|
||||
private readonly radius: number
|
||||
private readonly cutoff = 0.5;
|
||||
readonly buffer: number;
|
||||
private readonly radius: number;
|
||||
|
||||
private gridOuter: Float64Array
|
||||
private gridInner: Float64Array
|
||||
private f: Float64Array
|
||||
private d: Float64Array
|
||||
private z: Float64Array
|
||||
private v: Int16Array
|
||||
private gridOuter: Float64Array;
|
||||
private gridInner: Float64Array;
|
||||
private f: Float64Array;
|
||||
private d: Float64Array;
|
||||
private z: Float64Array;
|
||||
private v: Int16Array;
|
||||
|
||||
private scratchCanvas: HTMLCanvasElement
|
||||
private scratchContext: CanvasRenderingContext2D
|
||||
private scratchCanvas: HTMLCanvasElement;
|
||||
private scratchContext: CanvasRenderingContext2D;
|
||||
|
||||
readonly lineHeight: number
|
||||
readonly lineHeight: number;
|
||||
|
||||
private readonly maxWidth: number
|
||||
private readonly middle: number
|
||||
private readonly maxWidth: number;
|
||||
private readonly middle: number;
|
||||
|
||||
constructor(props: Partial<FontAtlasProps> = {}) {
|
||||
const p = { ...PD.getDefaultValues(FontAtlasParams), ...props };
|
||||
|
||||
@@ -510,10 +510,10 @@ export function applyTextureMeshSubstanceSmoothing(values: TextureMeshValues, re
|
||||
|
||||
stride *= 3; // triple because TextureMesh is never indexed (no elements buffer)
|
||||
|
||||
if (!webgl.namedTextures[ColorSmoothingRgbName]) {
|
||||
webgl.namedTextures[ColorSmoothingRgbName] = webgl.resources.texture('image-uint8', 'rgb', 'ubyte', 'nearest');
|
||||
if (!webgl.namedTextures[ColorSmoothingRgbaName]) {
|
||||
webgl.namedTextures[ColorSmoothingRgbaName] = webgl.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
|
||||
}
|
||||
const colorData = webgl.namedTextures[ColorSmoothingRgbName];
|
||||
const colorData = webgl.namedTextures[ColorSmoothingRgbaName];
|
||||
colorData.load(values.tSubstance.ref.value);
|
||||
|
||||
const smoothingData = calcTextureMeshColorSmoothing({
|
||||
|
||||
@@ -47,7 +47,7 @@ export interface TextureMesh {
|
||||
export namespace TextureMesh {
|
||||
export class DoubleBuffer {
|
||||
private index = 0;
|
||||
private textures: ({ vertex: Texture, group: Texture, normal: Texture } | undefined)[] = []
|
||||
private textures: ({ vertex: Texture, group: Texture, normal: Texture } | undefined)[] = [];
|
||||
|
||||
get() {
|
||||
return this.textures[this.index];
|
||||
@@ -113,6 +113,8 @@ export namespace TextureMesh {
|
||||
flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
||||
bumpFrequency: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
bumpAmplitude: PD.Numeric(1, { min: 0, max: 5, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
export type Params = typeof Params
|
||||
|
||||
@@ -168,6 +170,8 @@ export namespace TextureMesh {
|
||||
dFlipSided: ValueCell.create(props.flipSided),
|
||||
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
||||
dXrayShaded: ValueCell.create(props.xrayShaded),
|
||||
uBumpFrequency: ValueCell.create(props.bumpFrequency),
|
||||
uBumpAmplitude: ValueCell.create(props.bumpAmplitude),
|
||||
dGeoTexture: ValueCell.create(true),
|
||||
|
||||
meta: ValueCell.create(textureMesh.meta),
|
||||
@@ -187,6 +191,8 @@ export namespace TextureMesh {
|
||||
ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
||||
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
||||
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
||||
ValueCell.updateIfChanged(values.uBumpFrequency, props.bumpFrequency);
|
||||
ValueCell.updateIfChanged(values.uBumpAmplitude, props.bumpAmplitude);
|
||||
}
|
||||
|
||||
function updateBoundingSphere(values: TextureMeshValues, textureMesh: TextureMesh) {
|
||||
|
||||
@@ -72,7 +72,7 @@ export function computeMarchingCubesLines(params: MarchingCubesParams, lines?: L
|
||||
class MarchingCubesComputation {
|
||||
private size: number;
|
||||
private sliceSize: number;
|
||||
private edgeFilter: number
|
||||
private edgeFilter: number;
|
||||
|
||||
private minX = 0; private minY = 0; private minZ = 0;
|
||||
private maxX = 0; private maxY = 0; private maxZ = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -7,7 +7,7 @@
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec, GlobalTextureSchema } from './schema';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec, GlobalTextureSchema, UniformSpec } from './schema';
|
||||
import { CylindersShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
|
||||
@@ -26,6 +26,8 @@ export const CylindersSchema = {
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
};
|
||||
export type CylindersSchema = typeof CylindersSchema
|
||||
export type CylindersValues = Values<CylindersSchema>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -7,7 +7,7 @@
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema, InternalValues, GlobalTextureSchema, ValueSpec } from './schema';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema, InternalValues, GlobalTextureSchema, ValueSpec, UniformSpec } from './schema';
|
||||
import { MeshShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
|
||||
@@ -22,6 +22,8 @@ export const MeshSchema = {
|
||||
dFlipSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
meta: ValueSpec('unknown')
|
||||
} as const;
|
||||
export type MeshSchema = typeof MeshSchema
|
||||
|
||||
@@ -243,12 +243,12 @@ export type TransparencyValues = Values<TransparencySchema>
|
||||
|
||||
export const SubstanceSchema = {
|
||||
uSubstanceTexDim: UniformSpec('v2'),
|
||||
tSubstance: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'),
|
||||
tSubstance: TextureSpec('image-uint8', 'rgba', 'ubyte', 'nearest'),
|
||||
dSubstance: DefineSpec('boolean'),
|
||||
|
||||
uSubstanceGridDim: UniformSpec('v3'),
|
||||
uSubstanceGridTransform: UniformSpec('v4'),
|
||||
tSubstanceGrid: TextureSpec('texture', 'rgb', 'ubyte', 'linear'),
|
||||
tSubstanceGrid: TextureSpec('texture', 'rgba', 'ubyte', 'linear'),
|
||||
dSubstanceType: DefineSpec('string', ['groupInstance', 'volumeInstance']),
|
||||
} as const;
|
||||
export type SubstanceSchema = typeof SubstanceSchema
|
||||
@@ -288,6 +288,7 @@ export const BaseSchema = {
|
||||
uAlpha: UniformSpec('f', 'material'),
|
||||
uMetalness: UniformSpec('f', 'material'),
|
||||
uRoughness: UniformSpec('f', 'material'),
|
||||
uBumpiness: UniformSpec('f', 'material'),
|
||||
|
||||
uVertexCount: UniformSpec('i'),
|
||||
uInstanceCount: UniformSpec('i'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -7,7 +7,7 @@
|
||||
import { Renderable, RenderableState, createRenderable } from '../renderable';
|
||||
import { WebGLContext } from '../webgl/context';
|
||||
import { createGraphicsRenderItem } from '../webgl/render-item';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec, GlobalTextureSchema } from './schema';
|
||||
import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec, GlobalTextureSchema, UniformSpec } from './schema';
|
||||
import { SpheresShaderCode } from '../shader-code';
|
||||
import { ValueCell } from '../../mol-util';
|
||||
|
||||
@@ -23,6 +23,8 @@ export const SpheresSchema = {
|
||||
dDoubleSided: DefineSpec('boolean'),
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
};
|
||||
export type SpheresSchema = typeof SpheresSchema
|
||||
export type SpheresValues = Values<SpheresSchema>
|
||||
|
||||
@@ -24,6 +24,8 @@ export const TextureMeshSchema = {
|
||||
dIgnoreLight: DefineSpec('boolean'),
|
||||
dXrayShaded: DefineSpec('boolean'),
|
||||
dGeoTexture: DefineSpec('boolean'),
|
||||
uBumpFrequency: UniformSpec('f'),
|
||||
uBumpAmplitude: UniformSpec('f'),
|
||||
meta: ValueSpec('unknown')
|
||||
};
|
||||
export type TextureMeshSchema = typeof TextureMeshSchema
|
||||
|
||||
@@ -8,17 +8,16 @@
|
||||
*/
|
||||
|
||||
export const apply_light_color = `
|
||||
// inputs
|
||||
// - vec4 material
|
||||
// - vec3 vViewPosition
|
||||
// - vec3 normal
|
||||
// - float uMetalness
|
||||
// - float uRoughness
|
||||
// - vec3 uLightColor
|
||||
// - vec3 uAmbientColor
|
||||
|
||||
// outputs
|
||||
// - sets gl_FragColor
|
||||
#ifdef bumpEnabled
|
||||
if (uBumpFrequency > 0.0 && uBumpAmplitude > 0.0) {
|
||||
vec3 bumpNormal = perturbNormal(-vViewPosition, normal, fbm(vModelPosition * uBumpFrequency), (uBumpAmplitude * bumpiness) / uBumpFrequency);
|
||||
#ifdef enabledFragDepth
|
||||
if (!any(isNaN(bumpNormal))) normal = bumpNormal;
|
||||
#else
|
||||
normal = bumpNormal;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 color = material;
|
||||
|
||||
@@ -26,7 +25,13 @@ ReflectedLight reflectedLight = ReflectedLight(vec3(0.0), vec3(0.0), vec3(0.0),
|
||||
|
||||
PhysicalMaterial physicalMaterial;
|
||||
physicalMaterial.diffuseColor = color.rgb * (1.0 - metalness);
|
||||
physicalMaterial.roughness = max(roughness, 0.0525);
|
||||
#ifdef enabledFragDepth
|
||||
physicalMaterial.roughness = min(max(roughness, 0.0525), 1.0);
|
||||
#else
|
||||
vec3 dxy = max(abs(dFdx(normal)), abs(dFdy(normal)));
|
||||
float geometryRoughness = max(max(dxy.x, dxy.y), dxy.z);
|
||||
physicalMaterial.roughness = min(max(roughness, 0.0525) + geometryRoughness, 1.0);
|
||||
#endif
|
||||
physicalMaterial.specularColor = mix(vec3(0.04), color.rgb, metalness);
|
||||
physicalMaterial.specularF90 = 1.0;
|
||||
|
||||
|
||||
@@ -44,16 +44,16 @@ export const assign_color_varying = `
|
||||
|
||||
#ifdef dSubstance
|
||||
#if defined(dSubstanceType_groupInstance)
|
||||
vSubstance = readFromTexture(tSubstance, aInstance * float(uGroupCount) + group, uSubstanceTexDim).rgb;
|
||||
vSubstance = readFromTexture(tSubstance, aInstance * float(uGroupCount) + group, uSubstanceTexDim);
|
||||
#elif defined(dSubstanceType_vertexInstance)
|
||||
vSubstance = readFromTexture(tSubstance, int(aInstance) * uVertexCount + VertexID, uSubstanceTexDim).rgb;
|
||||
vSubstance = readFromTexture(tSubstance, int(aInstance) * uVertexCount + VertexID, uSubstanceTexDim);
|
||||
#elif defined(dSubstanceType_volumeInstance)
|
||||
vec3 sgridPos = (uSubstanceGridTransform.w * (vModelPosition - uSubstanceGridTransform.xyz)) / uSubstanceGridDim;
|
||||
vSubstance = texture3dFrom2dLinear(tSubstanceGrid, sgridPos, uSubstanceGridDim, uSubstanceTexDim).rgb;
|
||||
vSubstance = texture3dFrom2dLinear(tSubstanceGrid, sgridPos, uSubstanceGridDim, uSubstanceTexDim);
|
||||
#endif
|
||||
|
||||
// pre-mix to avoid artifacts due to empty substance
|
||||
vSubstance.rg = mix(vec2(uMetalness, uRoughness), vSubstance.rg, vSubstance.b);
|
||||
vSubstance.rgb = mix(vec3(uMetalness, uRoughness, uBumpiness), vSubstance.rgb, vSubstance.a);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
|
||||
@@ -23,9 +23,11 @@ export const assign_material_color = `
|
||||
|
||||
float metalness = uMetalness;
|
||||
float roughness = uRoughness;
|
||||
float bumpiness = uBumpiness;
|
||||
#ifdef dSubstance
|
||||
metalness = mix(metalness, vSubstance.r, vSubstance.b);
|
||||
roughness = mix(roughness, vSubstance.g, vSubstance.b);
|
||||
metalness = mix(metalness, vSubstance.r, vSubstance.a);
|
||||
roughness = mix(roughness, vSubstance.g, vSubstance.a);
|
||||
bumpiness = mix(bumpiness, vSubstance.b, vSubstance.a);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
vec4 material = vColor;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
export const color_frag_params = `
|
||||
uniform float uMetalness;
|
||||
uniform float uRoughness;
|
||||
uniform float uBumpiness;
|
||||
#ifdef bumpEnabled
|
||||
uniform float uBumpFrequency;
|
||||
uniform float uBumpAmplitude;
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_color)
|
||||
#if defined(dColorType_uniform)
|
||||
@@ -14,7 +19,7 @@ uniform float uRoughness;
|
||||
#endif
|
||||
|
||||
#ifdef dSubstance
|
||||
varying vec3 vSubstance;
|
||||
varying vec4 vSubstance;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
#if __VERSION__ == 100
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export const color_vert_params = `
|
||||
uniform float uMetalness;
|
||||
uniform float uRoughness;
|
||||
uniform float uBumpiness;
|
||||
|
||||
#if defined(dRenderVariant_color)
|
||||
#if defined(dColorType_uniform)
|
||||
@@ -36,11 +37,11 @@ uniform float uRoughness;
|
||||
|
||||
#ifdef dSubstance
|
||||
#if defined(dSubstanceType_groupInstance) || defined(dSubstanceType_vertexInstance)
|
||||
varying vec3 vSubstance;
|
||||
varying vec4 vSubstance;
|
||||
uniform vec2 uSubstanceTexDim;
|
||||
uniform sampler2D tSubstance;
|
||||
#elif defined(dSubstanceType_volumeInstance)
|
||||
varying vec3 vSubstance;
|
||||
varying vec4 vSubstance;
|
||||
uniform vec2 uSubstanceTexDim;
|
||||
uniform vec3 uSubstanceGridDim;
|
||||
uniform vec4 uSubstanceGridTransform;
|
||||
|
||||
@@ -76,4 +76,49 @@ float calcDepth(const in vec3 pos) {
|
||||
vec2 clipZW = pos.z * uProjection[2].zw + uProjection[3].zw;
|
||||
return 0.5 + 0.5 * clipZW.x / clipZW.y;
|
||||
}
|
||||
|
||||
// "Bump Mapping Unparametrized Surfaces on the GPU" Morten S. Mikkelsen
|
||||
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
|
||||
vec3 perturbNormal(in vec3 position, in vec3 normal, in float height, in float scale) {
|
||||
vec3 sigmaS = dFdx(position);
|
||||
vec3 sigmaT = dFdy(position);
|
||||
|
||||
vec3 r1 = cross(sigmaT, normal);
|
||||
vec3 r2 = cross(normal, sigmaS);
|
||||
float det = dot(sigmaS, r1);
|
||||
|
||||
float bs = dFdx(height);
|
||||
float bt = dFdy(height);
|
||||
|
||||
vec3 surfGrad = sign(det) * (bs * r1 + bt * r2);
|
||||
return normalize(abs(det) * normal - scale * surfGrad);
|
||||
}
|
||||
|
||||
float hash(in float h) {
|
||||
return fract(sin(h) * 43758.5453123);
|
||||
}
|
||||
|
||||
float noise(in vec3 x) {
|
||||
vec3 p = floor(x);
|
||||
vec3 f = fract(x);
|
||||
f = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
float n = p.x + p.y * 157.0 + 113.0 * p.z;
|
||||
return mix(
|
||||
mix(mix(hash(n + 0.0), hash(n + 1.0), f.x),
|
||||
mix(hash(n + 157.0), hash(n + 158.0), f.x), f.y),
|
||||
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
|
||||
mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y), f.z);
|
||||
}
|
||||
|
||||
float fbm(in vec3 p) {
|
||||
float f = 0.0;
|
||||
f += 0.5 * noise(p);
|
||||
p *= 2.01;
|
||||
f += 0.25 * noise(p);
|
||||
p *= 2.02;
|
||||
f += 0.125 * noise(p);
|
||||
|
||||
return f;
|
||||
}
|
||||
`;
|
||||
@@ -214,6 +214,9 @@ float depthToViewZ(const in float isOrtho, const in float linearClipZ, const in
|
||||
a31 * b01 - a30 * b03 - a32 * b00,
|
||||
a20 * b03 - a21 * b01 + a22 * b00) / det;
|
||||
}
|
||||
|
||||
#define isNaN(x) ( (x) != (x) )
|
||||
#define isInf(x) ( (x) == (x)+1. )
|
||||
#else
|
||||
#define transpose2(m) transpose(m)
|
||||
#define transpose3(m) transpose(m)
|
||||
@@ -222,5 +225,8 @@ float depthToViewZ(const in float isOrtho, const in float linearClipZ, const in
|
||||
#define inverse2(m) inverse(m)
|
||||
#define inverse3(m) inverse(m)
|
||||
#define inverse4(m) inverse(m)
|
||||
|
||||
#define isNaN isnan
|
||||
#define isInf isinf
|
||||
#endif
|
||||
`;
|
||||
@@ -8,8 +8,10 @@
|
||||
*/
|
||||
|
||||
export const light_frag_params = `
|
||||
uniform vec3 uLightDirection[dLightCount];
|
||||
uniform vec3 uLightColor[dLightCount];
|
||||
#if dLightCount != 0
|
||||
uniform vec3 uLightDirection[dLightCount];
|
||||
uniform vec3 uLightColor[dLightCount];
|
||||
#endif
|
||||
uniform vec3 uAmbientColor;
|
||||
|
||||
struct PhysicalMaterial {
|
||||
|
||||
@@ -8,6 +8,8 @@ export const cylinders_frag = `
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
|
||||
#define bumpEnabled
|
||||
|
||||
uniform mat4 uView;
|
||||
|
||||
varying mat4 vTransform;
|
||||
@@ -18,6 +20,7 @@ varying float vCap;
|
||||
|
||||
uniform vec3 uCameraDir;
|
||||
uniform vec3 uCameraPosition;
|
||||
uniform mat4 uInvView;
|
||||
|
||||
#include common
|
||||
#include common_frag_params
|
||||
@@ -108,7 +111,8 @@ void main() {
|
||||
vViewPosition = (uView * vec4(vViewPosition, 1.0)).xyz;
|
||||
gl_FragDepthEXT = calcDepth(vViewPosition);
|
||||
|
||||
// bugfix (mac only?)
|
||||
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
|
||||
|
||||
if (gl_FragDepthEXT < 0.0) discard;
|
||||
if (gl_FragDepthEXT > 1.0) discard;
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ uniform vec3 uFogColor;
|
||||
uniform float uAlpha;
|
||||
uniform float uPickingAlphaThreshold;
|
||||
uniform bool uTransparentBackground;
|
||||
uniform float uXrayEdgeFalloff;
|
||||
|
||||
uniform float uInteriorDarkening;
|
||||
uniform bool uInteriorColorFlag;
|
||||
|
||||
@@ -8,6 +8,8 @@ export const mesh_frag = `
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
|
||||
#define bumpEnabled
|
||||
|
||||
#include common
|
||||
#include common_frag_params
|
||||
#include color_frag_params
|
||||
|
||||
@@ -21,6 +21,7 @@ uniform float uFar;
|
||||
uniform float uFogNear;
|
||||
uniform float uFogFar;
|
||||
uniform vec3 uFogColor;
|
||||
uniform vec3 uOutlineColor;
|
||||
uniform bool uTransparentBackground;
|
||||
|
||||
uniform float uOcclusionBias;
|
||||
@@ -116,7 +117,7 @@ void main(void) {
|
||||
float outline = getOutline(coords, closestTexel);
|
||||
|
||||
if (outline == 0.0) {
|
||||
color.rgb *= outline;
|
||||
color.rgb = mix(uOutlineColor, color.rgb, outline);
|
||||
viewDist = abs(getViewZ(closestTexel));
|
||||
fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
|
||||
if (!uTransparentBackground) {
|
||||
|
||||
@@ -8,12 +8,16 @@ export const spheres_frag = `
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
|
||||
#define bumpEnabled
|
||||
|
||||
#include common
|
||||
#include common_frag_params
|
||||
#include color_frag_params
|
||||
#include light_frag_params
|
||||
#include common_clip
|
||||
|
||||
uniform mat4 uInvView;
|
||||
|
||||
varying float vRadius;
|
||||
varying float vRadiusSq;
|
||||
varying vec3 vPoint;
|
||||
@@ -73,7 +77,8 @@ void main(void){
|
||||
gl_FragDepthEXT = 0.0 + (0.0000001 / vRadius);
|
||||
}
|
||||
|
||||
// bugfix (mac only?)
|
||||
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
|
||||
|
||||
if (gl_FragDepthEXT < 0.0) discard;
|
||||
if (gl_FragDepthEXT > 1.0) discard;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.352, IHM 1.17, CARB draft.
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.353, IHM 1.17, MA 1.3.3.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
@@ -942,6 +942,48 @@ export const mmCIF_Schema = {
|
||||
*/
|
||||
method: Aliased<'X-RAY DIFFRACTION' | 'NEUTRON DIFFRACTION' | 'FIBER DIFFRACTION' | 'ELECTRON CRYSTALLOGRAPHY' | 'ELECTRON MICROSCOPY' | 'SOLUTION NMR' | 'SOLID-STATE NMR' | 'SOLUTION SCATTERING' | 'POWDER DIFFRACTION' | 'INFRARED SPECTROSCOPY' | 'EPR' | 'FLUORESCENCE TRANSFER' | 'THEORETICAL MODEL'>(str),
|
||||
},
|
||||
/**
|
||||
* Data items in the SOFTWARE category record details about
|
||||
* the software used in the structure analysis, which implies
|
||||
* any software used in the generation of any data items
|
||||
* associated with the structure determination and
|
||||
* structure representation.
|
||||
*
|
||||
* These data items allow computer programs to be referenced
|
||||
* in more detail than data items in the COMPUTING category do.
|
||||
*/
|
||||
software: {
|
||||
/**
|
||||
* The classification of the program according to its
|
||||
* major function.
|
||||
*/
|
||||
classification: str,
|
||||
/**
|
||||
* The date the software was released.
|
||||
*/
|
||||
date: str,
|
||||
/**
|
||||
* Description of the software.
|
||||
*/
|
||||
description: str,
|
||||
/**
|
||||
* The name of the software.
|
||||
*/
|
||||
name: str,
|
||||
/**
|
||||
* The classification of the software according to the most
|
||||
* common types.
|
||||
*/
|
||||
type: Aliased<'program' | 'library' | 'package' | 'filter' | 'jiffy' | 'other'>(str),
|
||||
/**
|
||||
* The version of the software.
|
||||
*/
|
||||
version: str,
|
||||
/**
|
||||
* An ordinal index for this category
|
||||
*/
|
||||
pdbx_ordinal: int,
|
||||
},
|
||||
/**
|
||||
* Data items in the STRUCT category record details about the
|
||||
* description of the crystallographic structure.
|
||||
@@ -4717,6 +4759,289 @@ export const mmCIF_Schema = {
|
||||
*/
|
||||
dataset_list_id: int,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_MODEL_LIST category record the
|
||||
* details of the models being deposited.
|
||||
*/
|
||||
ma_model_list: {
|
||||
/**
|
||||
* A unique identifier for the model / model group combination.
|
||||
*/
|
||||
ordinal_id: int,
|
||||
/**
|
||||
* A unique identifier for the structural model being deposited.
|
||||
*/
|
||||
model_id: int,
|
||||
/**
|
||||
* An identifier to group structural models into collections or sets.
|
||||
* A cluster of models and its representative can either be grouped together
|
||||
* or can be separate groups in the ma_model_list table. The choice between
|
||||
* the two options should be decided based on how the modeling was carried out
|
||||
* and how the representative was chosen. If the representative is a member of
|
||||
* the ensemble (i.e., best scoring model), then it is recommended that the
|
||||
* representative and the ensemble belong to the same model group. If the
|
||||
* representative is calculated from the ensemble (i.e., centroid), then it is
|
||||
* recommended that the representative be separated into a different group.
|
||||
* If the models do not need to be grouped into collections, then the
|
||||
* _ma_model_list.model_group_id is the same as _ma_model_list.model_id.
|
||||
*/
|
||||
model_group_id: int,
|
||||
/**
|
||||
* A decsriptive name for the model.
|
||||
*/
|
||||
model_name: str,
|
||||
/**
|
||||
* A decsriptive name for the model group.
|
||||
*/
|
||||
model_group_name: str,
|
||||
/**
|
||||
* The type of model.
|
||||
*/
|
||||
model_type: Aliased<'Homology model' | 'Ab initio model' | 'Other'>(str),
|
||||
/**
|
||||
* The data_id identifier. This data item is a pointer to
|
||||
* _ma_data.id in the MA_DATA category.
|
||||
*/
|
||||
data_id: int,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_TARGET_ENTITY category record details about
|
||||
* the target entities. The details are provided for each entity
|
||||
* being modeled.
|
||||
*/
|
||||
ma_target_entity: {
|
||||
/**
|
||||
* A unique identifier for the distinct molecular entity of the target.
|
||||
* This data item is a pointer to _entity.id in the ENTITY category.
|
||||
*/
|
||||
entity_id: str,
|
||||
/**
|
||||
* The data_id identifier. This data item is a pointer to
|
||||
* _ma_data.id in the MA_DATA category.
|
||||
*/
|
||||
data_id: int,
|
||||
/**
|
||||
* The origin of the target entity.
|
||||
*/
|
||||
origin: Aliased<'reference database' | 'designed'>(str),
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_TARGET_ENTITY_INSTANCE category record details about
|
||||
* the instances of target entities modeled.
|
||||
*/
|
||||
ma_target_entity_instance: {
|
||||
/**
|
||||
* A unique identifier for the instance of the entity.
|
||||
*/
|
||||
asym_id: str,
|
||||
/**
|
||||
* A unique identifier for the distinct molecular entity of the target.
|
||||
* This data item is a pointer to _ma_target_entity.entity_id in the
|
||||
* MA_TARGET_ENTITY category.
|
||||
*/
|
||||
entity_id: str,
|
||||
/**
|
||||
* Additional details about the entity instance.
|
||||
*/
|
||||
details: str,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_TARGET_REF_DB_DETAILS category record details about
|
||||
* the reference databases for the target sequences.
|
||||
*/
|
||||
ma_target_ref_db_details: {
|
||||
/**
|
||||
* An identifier for the target entity.
|
||||
*/
|
||||
target_entity_id: str,
|
||||
/**
|
||||
* The name of the database containing reference information about
|
||||
* this entity or biological unit.
|
||||
*/
|
||||
db_name: Aliased<'UNP' | 'GB' | 'OrthoDB' | 'NCBI' | 'JGI' | 'Other'>(str),
|
||||
/**
|
||||
* The code for this entity or biological unit or for a closely
|
||||
* related entity or biological unit in the named database.
|
||||
* This can include the version number.
|
||||
*/
|
||||
db_code: str,
|
||||
/**
|
||||
* Accession code assigned by the reference database.
|
||||
*/
|
||||
db_accession: str,
|
||||
/**
|
||||
* Database code assigned by the reference database for a sequence isoform. An isoform sequence is an
|
||||
* alternative protein sequence that can be generated from the same gene by a single or by a combination of
|
||||
* biological events such as: alternative promoter usage, alternative splicing, alternative initiation
|
||||
* and ribosomal frameshifting.
|
||||
*/
|
||||
seq_db_isoform: str,
|
||||
/**
|
||||
* Beginning index in the chemical sequence from the
|
||||
* reference database.
|
||||
*/
|
||||
seq_db_align_begin: str,
|
||||
/**
|
||||
* Ending index in the chemical sequence from the
|
||||
* reference database.
|
||||
*/
|
||||
seq_db_align_end: str,
|
||||
/**
|
||||
* Taxonomy identifier provided by NCBI.
|
||||
*/
|
||||
ncbi_taxonomy_id: str,
|
||||
/**
|
||||
* Scientific name of the organism.
|
||||
*/
|
||||
organism_scientific: str,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_DATA category capture the different kinds of
|
||||
* data used in the modeling. These can be multiple sequence
|
||||
* alignments, spatial restraints, template structures etc.
|
||||
*/
|
||||
ma_data: {
|
||||
/**
|
||||
* A unique identifier for the data.
|
||||
*/
|
||||
id: int,
|
||||
/**
|
||||
* The type of data held in the dataset.
|
||||
*/
|
||||
content_type: Aliased<'target' | 'template structure' | 'polymeric template library' | 'spatial restraints' | 'target-template alignment' | 'coevolution MSA' | 'model coordinates' | 'other'>(str),
|
||||
/**
|
||||
* Details for other content types.
|
||||
*/
|
||||
content_type_other_details: str,
|
||||
/**
|
||||
* An author-given name for the content held in the dataset.
|
||||
*/
|
||||
name: str,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_SOFTWARE_GROUP category describes the
|
||||
* collection of software into groups so that they can be used
|
||||
* efficiently in the MA_PROTOCOL_STEP category.
|
||||
*/
|
||||
ma_software_group: {
|
||||
/**
|
||||
* A unique identifier for the category.
|
||||
*/
|
||||
ordinal_id: int,
|
||||
/**
|
||||
* An identifier for the group entry.
|
||||
* If data does not need to be grouped, then _ma_software_group.group_id
|
||||
* is the same as _ma_software_group.software_id.
|
||||
*/
|
||||
group_id: int,
|
||||
/**
|
||||
* The identifier for the software.
|
||||
* This data item is a pointer to _software.pdbx_ordinal
|
||||
* in the SOFTWARE category.
|
||||
*/
|
||||
software_id: int,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_QA_METRIC category record the
|
||||
* details of the metrics use to assess model quality.
|
||||
*/
|
||||
ma_qa_metric: {
|
||||
/**
|
||||
* An identifier for the QA metric.
|
||||
*/
|
||||
id: int,
|
||||
/**
|
||||
* Name of the QA metric.
|
||||
*/
|
||||
name: str,
|
||||
/**
|
||||
* The type of QA metric.
|
||||
*/
|
||||
type: Aliased<'zscore' | 'energy' | 'distance' | 'normalized score' | 'pLDDT' | 'PAE' | 'contact probability' | 'other'>(str),
|
||||
/**
|
||||
* The mode of calculation of the QA metric.
|
||||
*/
|
||||
mode: Aliased<'local' | 'global' | 'local-pairwise'>(str),
|
||||
/**
|
||||
* Identifier to the set of software used to calculate the QA metric.
|
||||
* This data item is a pointer to the _ma_software_group.group_id in the
|
||||
* MA_SOFTWARE_GROUP category.
|
||||
*/
|
||||
software_group_id: int,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_QA_METRIC_GLOBAL category captures the
|
||||
* details of the global QA metrics, calculated at the model-level.
|
||||
*/
|
||||
ma_qa_metric_global: {
|
||||
/**
|
||||
* A unique identifier for the category.
|
||||
*/
|
||||
ordinal_id: int,
|
||||
/**
|
||||
* The identifier for the structural model, for which global QA metric is provided.
|
||||
* This data item is a pointer to _ma_model_list.model_id
|
||||
* in the MA_MODEL_LIST category.
|
||||
*/
|
||||
model_id: int,
|
||||
/**
|
||||
* The identifier for the QA metric.
|
||||
* This data item is a pointer to _ma_qa_metric.id in the
|
||||
* MA_QA_METRIC category.
|
||||
*/
|
||||
metric_id: int,
|
||||
/**
|
||||
* The value of the global QA metric.
|
||||
*/
|
||||
metric_value: float,
|
||||
},
|
||||
/**
|
||||
* Data items in the MA_QA_METRIC_LOCAL category captures the
|
||||
* details of the local QA metrics, calculated at the residue-level.
|
||||
*/
|
||||
ma_qa_metric_local: {
|
||||
/**
|
||||
* A unique identifier for the category.
|
||||
*/
|
||||
ordinal_id: int,
|
||||
/**
|
||||
* The identifier for the structural model, for which local QA metric is provided.
|
||||
* This data item is a pointer to _ma_model_list.model_id
|
||||
* in the MA_MODEL_LIST category.
|
||||
*/
|
||||
model_id: int,
|
||||
/**
|
||||
* The identifier for the asym id of the residue in the
|
||||
* structural model, for which local QA metric is provided.
|
||||
* This data item is a pointer to _atom_site.label_asym_id
|
||||
* in the ATOM_SITE category.
|
||||
*/
|
||||
label_asym_id: str,
|
||||
/**
|
||||
* The identifier for the sequence index of the residue
|
||||
* in the structural model, for which local QA metric is provided.
|
||||
* This data item is a pointer to _atom_site.label_seq_id
|
||||
* in the ATOM_SITE category.
|
||||
*/
|
||||
label_seq_id: int,
|
||||
/**
|
||||
* The component identifier for the residue in the
|
||||
* structural model, for which local QA metric is provided.
|
||||
* This data item is a pointer to _atom_site.label_comp_id
|
||||
* in the ATOM_SITE category.
|
||||
*/
|
||||
label_comp_id: str,
|
||||
/**
|
||||
* The identifier for the QA metric.
|
||||
* This data item is a pointer to _ma_qa_metric.id in the
|
||||
* MA_QA_METRIC category.
|
||||
*/
|
||||
metric_id: int,
|
||||
/**
|
||||
* The value of the local QA metric.
|
||||
*/
|
||||
metric_value: float,
|
||||
},
|
||||
};
|
||||
|
||||
export type mmCIF_Schema = typeof mmCIF_Schema;
|
||||
|
||||
@@ -12,12 +12,12 @@ import { Box3D } from './primitives/box3d';
|
||||
// implementing http://www.ep.liu.se/ecp/034/009/ecp083409.pdf
|
||||
|
||||
export class BoundaryHelper {
|
||||
private dir: Vec3[]
|
||||
private dir: Vec3[];
|
||||
|
||||
private minDist: number[] = []
|
||||
private maxDist: number[] = []
|
||||
private extrema: Vec3[] = []
|
||||
centroidHelper = new CentroidHelper()
|
||||
private minDist: number[] = [];
|
||||
private maxDist: number[] = [];
|
||||
private extrema: Vec3[] = [];
|
||||
centroidHelper = new CentroidHelper();
|
||||
|
||||
private computeExtrema(i: number, p: Vec3) {
|
||||
const d = Vec3.dot(this.dir[i], p);
|
||||
|
||||
@@ -27,7 +27,7 @@ class GridLookup3DImpl<T extends number = number> implements GridLookup3D<T> {
|
||||
private ctx: QueryContext;
|
||||
boundary: Lookup3D['boundary'];
|
||||
buckets: GridLookup3D['buckets'];
|
||||
result: Result<T>
|
||||
result: Result<T>;
|
||||
|
||||
find(x: number, y: number, z: number, radius: number, result?: Result<T>): Result<T> {
|
||||
this.ctx.x = x;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user