Compare commits

..

30 Commits

Author SHA1 Message Date
Alexander Rose
80323d8122 2.0.0-dev.5 2021-03-06 13:59:17 -08:00
Alexander Rose
cbd6aa0b6b use 32bit depth texture in webgl2 2021-03-06 13:27:04 -08:00
Alexander Rose
3831bd9941 improve handling of coarse grained models 2021-03-06 11:17:43 -08:00
dsehnal
3d3e2c3a86 packages 2021-03-05 00:48:49 +01:00
dsehnal
bc5d796653 make pairingThreshold slightly larger 2021-03-04 19:14:35 +01:00
dsehnal
82dd0496c2 covalentlyBondedComponent query 2021-03-04 18:53:05 +01:00
dsehnal
056742ac74 model index animation loop direction 2021-03-04 18:37:47 +01:00
dsehnal
29d4cfbcca add xyz support 2021-03-04 18:10:39 +01:00
Alexander Rose
376449f7c8 add missing PRO to standard components 2021-03-03 17:51:17 -08:00
Alexander Rose
bc37fad007 2.0.0-dev.4 2021-02-27 18:29:41 -08:00
Alexander Rose
2e561a8de7 added interesting pdb entry 2021-02-27 18:25:34 -08:00
Alexander Rose
e6c8c69d0c fix texture-mesh rendering artifacts
- added double buffering for texture-mesh textures
- added buffered uniforms
2021-02-27 18:25:06 -08:00
Alexander Rose
d121a11e28 tweaked structure-element export
- got rid of index.ts for better compatibility
2021-02-22 21:24:19 -08:00
dsehnal
5484a2a72c add logo to orbitals example 2021-02-22 18:56:03 +01:00
dsehnal
d527609b6d 2.0.0-dev.3 2021-02-21 19:23:06 +01:00
dsehnal
e628f580a7 add missing React key 2021-02-21 16:28:17 +01:00
Alexander Rose
b662179b4d improved lighting example 2021-02-20 01:59:46 -08:00
Alexander Rose
fa2b8542bf 2.0.0-dev.2 2021-02-18 21:20:14 -08:00
Alexander Rose
901522f500 added atom-id and entity-id color theme 2021-02-18 21:16:46 -08:00
dsehnal
62b63c1aa5 apply magic to solve GPU MC rendering issue 2021-02-18 19:05:07 +01:00
Alexander Rose
24b36f41da 2.0.0-dev.1 2021-02-15 22:09:05 -08:00
Alexander Rose
c9c890782c try re-use boundingSphere in element visuals
- if it has not changed much
2021-02-15 21:38:13 -08:00
Alexander Rose
f2c539ebd8 psf parser, support lammps "full" style 2021-02-15 18:04:38 -08:00
dsehnal
feb922ca91 Merge branch 'gpu' 2021-02-14 20:13:16 +01:00
dsehnal
25127bb84b Merge branch 'master' of https://github.com/molstar/molstar 2021-02-14 20:13:12 +01:00
dsehnal
8fb01d2157 Merge remote-tracking branch 'origin' into gpu 2021-02-14 20:11:11 +01:00
dsehnal
c09357ea75 updateImmediate for modelIndex 2021-02-14 20:00:37 +01:00
dsehnal
9f2513dae0 fix examples 2021-02-14 19:38:58 +01:00
dsehnal
11a52c0390 add missing TrajectoryInfo 2021-02-14 19:34:32 +01:00
dsehnal
e955dc7e94 exportable trajectory animation 2021-02-14 19:26:06 +01:00
56 changed files with 1352 additions and 272 deletions

View File

@@ -177,4 +177,4 @@ Funding sources include but are not limited to:
* [RCSB PDB](https://www.rcsb.org) funding by a grant [DBI-1338415; PI: SK Burley] from the NSF, the NIH, and the US DoE
* [PDBe, EMBL-EBI](https://pdbe.org)
* [CEITEC](https://www.ceitec.eu/)
* [EntosAI](https://www.entos.ai) (``alpha-orbitals`` extension)
* [EntosAI](https://www.entos.ai)

View File

@@ -26,3 +26,4 @@
* Protein (1BRR, 5Z6Y)
* DNA (5D3G)
* Multiple models with different sets of ligands or missing ligands (1J6T, 1VRC, 2ICY, 1O2F)
* Long linear sugar chain (4HG6)

442
package-lock.json generated
View File

@@ -1,11 +1,11 @@
{
"name": "molstar",
"version": "2.0.0-dev.0",
"version": "2.0.0-dev.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.2.15",
"version": "2.0.0-dev.4",
"license": "MIT",
"dependencies": {
"@types/argparse": "^1.0.38",
@@ -24,14 +24,14 @@
"cors": "^2.8.5",
"express": "^4.17.1",
"h264-mp4-encoder": "^1.0.12",
"immer": "^8.0.0",
"immer": "^8.0.1",
"immutable": "^3.8.2",
"node-fetch": "^2.6.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"rxjs": "^6.6.3",
"rxjs": "^6.6.6",
"swagger-ui-dist": "^3.37.2",
"tslib": "^2.0.3",
"tslib": "^2.1.0",
"util.promisify": "^1.0.1",
"xhr2": "^0.2.0"
},
@@ -74,7 +74,7 @@
"simple-git": "^2.25.0",
"style-loader": "^2.0.0",
"ts-jest": "^26.4.4",
"typescript": "^4.1.2",
"typescript": "^4.2.3",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-version-file-plugin": "^0.4.0"
@@ -92,6 +92,12 @@
"node": ">=8"
}
},
"node_modules/@ardatan/aggregate-error/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
@@ -1217,6 +1223,12 @@
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-codegen/add/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/cli": {
"version": "1.19.4",
"resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.19.4.tgz",
@@ -1324,6 +1336,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/@graphql-codegen/cli/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/core": {
"version": "1.17.9",
"resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.17.9.tgz",
@@ -1339,6 +1357,12 @@
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-codegen/core/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/plugin-helpers": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.2.tgz",
@@ -1408,6 +1432,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/@graphql-codegen/plugin-helpers/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/time": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@graphql-codegen/time/-/time-2.0.2.tgz",
@@ -1449,6 +1479,12 @@
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-codegen/typescript-graphql-files-modules/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/typescript-graphql-request": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-graphql-request/-/typescript-graphql-request-2.0.3.tgz",
@@ -1465,6 +1501,12 @@
"graphql-tag": "^2.0.0"
}
},
"node_modules/@graphql-codegen/typescript-graphql-request/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/typescript-operations": {
"version": "1.17.12",
"resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-1.17.12.tgz",
@@ -1481,6 +1523,18 @@
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-codegen/typescript-operations/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/typescript/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-codegen/visitor-plugin-common": {
"version": "1.17.21",
"resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.17.21.tgz",
@@ -1518,6 +1572,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/@graphql-codegen/visitor-plugin-common/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/apollo-engine-loader": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-6.2.5.tgz",
@@ -1546,6 +1606,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/apollo-engine-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/batch-execute": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-7.0.0.tgz",
@@ -1575,6 +1641,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/batch-execute/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/code-file-loader": {
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-6.2.6.tgz",
@@ -1603,6 +1675,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/code-file-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/delegate": {
"version": "7.0.7",
"resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-7.0.7.tgz",
@@ -1635,15 +1713,21 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/delegate/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/git-loader": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-6.2.5.tgz",
"integrity": "sha512-WOQDSzazyPZMZUvymHBv5oZ80/mS7tc8XUNy2GmU5My8YRny5zu4fEgP4vQeFcD1trG3uoHUaJPGF7Mmvp6Yhg==",
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-6.2.6.tgz",
"integrity": "sha512-ooQTt2CaG47vEYPP3CPD+nbA0F+FYQXfzrB1Y1ABN9K3d3O2RK3g8qwslzZaI8VJQthvKwt0A95ZeE4XxteYfw==",
"dev": true,
"dependencies": {
"@graphql-tools/graphql-tag-pluck": "^6.2.6",
"@graphql-tools/utils": "^7.0.0",
"tslib": "~2.0.1"
"tslib": "~2.1.0"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0"
@@ -1663,6 +1747,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/git-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/github-loader": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-6.2.5.tgz",
@@ -1692,6 +1782,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/github-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/graphql-file-loader": {
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-6.2.6.tgz",
@@ -1720,6 +1816,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/graphql-file-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/graphql-tag-pluck": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-6.3.0.tgz",
@@ -1754,6 +1856,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/graphql-tag-pluck/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/import": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-6.2.5.tgz",
@@ -1767,6 +1875,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/import/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/json-file-loader": {
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-6.2.6.tgz",
@@ -1794,6 +1908,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/json-file-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/load": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-6.2.5.tgz",
@@ -1828,6 +1948,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/load/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/merge": {
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.6.tgz",
@@ -1856,6 +1982,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/merge/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/optimize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@graphql-tools/optimize/-/optimize-1.0.1.tgz",
@@ -1868,6 +2000,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/optimize/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/prisma-loader": {
"version": "6.2.7",
"resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-6.2.7.tgz",
@@ -1916,6 +2054,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/prisma-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/relay-operation-optimizer": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.3.0.tgz",
@@ -1944,6 +2088,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/relay-operation-optimizer/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/schema": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.2.tgz",
@@ -1971,6 +2121,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/schema/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/url-loader": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-6.6.0.tgz",
@@ -2013,6 +2169,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/url-loader/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/utils": {
"version": "6.2.4",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.2.4.tgz",
@@ -2043,6 +2205,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/@graphql-tools/utils/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@graphql-tools/wrap": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-7.0.4.tgz",
@@ -2073,6 +2241,12 @@
"graphql": "^14.0.0 || ^15.0.0"
}
},
"node_modules/@graphql-tools/wrap/node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
},
"node_modules/@iarna/toml": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
@@ -8454,9 +8628,9 @@
}
},
"node_modules/immer": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/immer/-/immer-8.0.0.tgz",
"integrity": "sha512-jm87NNBAIG4fHwouilCHIecFXp5rMGkiFrAuhVO685UnMAlOneEAnOyzPt8OnP47TC11q/E7vpzZe0WvwepFTg==",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz",
"integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
@@ -13532,9 +13706,9 @@
}
},
"node_modules/rxjs": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
"integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==",
"version": "6.6.6",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.6.tgz",
"integrity": "sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg==",
"dependencies": {
"tslib": "^1.9.0"
},
@@ -15663,9 +15837,9 @@
}
},
"node_modules/tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
},
"node_modules/tsutils": {
"version": "3.17.1",
@@ -15773,9 +15947,9 @@
}
},
"node_modules/typescript": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -17571,6 +17745,14 @@
"dev": true,
"requires": {
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@babel/code-frame": {
@@ -18522,6 +18704,14 @@
"requires": {
"@graphql-codegen/plugin-helpers": "^1.18.2",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-codegen/cli": {
@@ -18628,6 +18818,12 @@
"dev": true
}
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18641,6 +18837,14 @@
"@graphql-tools/merge": "^6",
"@graphql-tools/utils": "^6",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-codegen/plugin-helpers": {
@@ -18714,6 +18918,12 @@
"dev": true
}
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18737,6 +18947,14 @@
"@graphql-codegen/visitor-plugin-common": "^1.17.21",
"auto-bind": "~4.0.0",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-codegen/typescript-graphql-files-modules": {
@@ -18747,6 +18965,14 @@
"requires": {
"@graphql-codegen/plugin-helpers": "^1.18.2",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-codegen/typescript-graphql-request": {
@@ -18759,6 +18985,14 @@
"@graphql-codegen/visitor-plugin-common": "^1.17.20",
"auto-bind": "~4.0.0",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-codegen/typescript-operations": {
@@ -18772,6 +19006,14 @@
"@graphql-codegen/visitor-plugin-common": "^1.17.20",
"auto-bind": "~4.0.0",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-codegen/visitor-plugin-common": {
@@ -18809,6 +19051,12 @@
"dev": true
}
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18833,6 +19081,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18858,6 +19112,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18882,6 +19142,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18910,18 +19176,24 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-tools/git-loader": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-6.2.5.tgz",
"integrity": "sha512-WOQDSzazyPZMZUvymHBv5oZ80/mS7tc8XUNy2GmU5My8YRny5zu4fEgP4vQeFcD1trG3uoHUaJPGF7Mmvp6Yhg==",
"version": "6.2.6",
"resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-6.2.6.tgz",
"integrity": "sha512-ooQTt2CaG47vEYPP3CPD+nbA0F+FYQXfzrB1Y1ABN9K3d3O2RK3g8qwslzZaI8VJQthvKwt0A95ZeE4XxteYfw==",
"dev": true,
"requires": {
"@graphql-tools/graphql-tag-pluck": "^6.2.6",
"@graphql-tools/utils": "^7.0.0",
"tslib": "~2.0.1"
"tslib": "~2.1.0"
},
"dependencies": {
"@graphql-tools/utils": {
@@ -18934,6 +19206,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18959,6 +19237,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -18983,6 +19267,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19010,6 +19300,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19021,6 +19317,14 @@
"requires": {
"resolve-from": "5.0.0",
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-tools/json-file-loader": {
@@ -19043,6 +19347,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19073,6 +19383,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19097,6 +19413,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19107,6 +19429,14 @@
"dev": true,
"requires": {
"tslib": "~2.0.1"
},
"dependencies": {
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
"@graphql-tools/prisma-loader": {
@@ -19150,6 +19480,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19174,6 +19510,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19197,6 +19539,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19235,6 +19583,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19266,6 +19620,12 @@
"dev": true
}
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -19292,6 +19652,12 @@
"camel-case": "4.1.2",
"tslib": "~2.0.1"
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==",
"dev": true
}
}
},
@@ -24455,9 +24821,9 @@
"dev": true
},
"immer": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/immer/-/immer-8.0.0.tgz",
"integrity": "sha512-jm87NNBAIG4fHwouilCHIecFXp5rMGkiFrAuhVO685UnMAlOneEAnOyzPt8OnP47TC11q/E7vpzZe0WvwepFTg=="
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz",
"integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA=="
},
"immutable": {
"version": "3.8.2",
@@ -28461,9 +28827,9 @@
}
},
"rxjs": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
"integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==",
"version": "6.6.6",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.6.tgz",
"integrity": "sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg==",
"requires": {
"tslib": "^1.9.0"
},
@@ -30176,9 +30542,9 @@
}
},
"tslib": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
"integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
},
"tsutils": {
"version": "3.17.1",
@@ -30264,9 +30630,9 @@
}
},
"typescript": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
"dev": true
},
"ua-parser-js": {

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "2.0.0-dev.0",
"version": "2.0.0-dev.5",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {
@@ -115,7 +115,7 @@
"simple-git": "^2.25.0",
"style-loader": "^2.0.0",
"ts-jest": "^26.4.4",
"typescript": "^4.1.2",
"typescript": "^4.2.3",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-version-file-plugin": "^0.4.0"
@@ -137,14 +137,14 @@
"cors": "^2.8.5",
"express": "^4.17.1",
"h264-mp4-encoder": "^1.0.12",
"immer": "^8.0.0",
"immer": "^8.0.1",
"immutable": "^3.8.2",
"node-fetch": "^2.6.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"rxjs": "^6.6.3",
"rxjs": "^6.6.6",
"swagger-ui-dist": "^3.37.2",
"tslib": "^2.0.3",
"tslib": "^2.1.0",
"util.promisify": "^1.0.1",
"xhr2": "^0.2.0"
}

View File

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

View File

@@ -53,8 +53,9 @@ export class AlphaOrbitalsExample {
plugin: PluginContext;
async init(target: string | HTMLElement) {
const defaultSpec = DefaultPluginSpec();
this.plugin = await createPluginAsync(typeof target === 'string' ? document.getElementById(target)! : target, {
...DefaultPluginSpec(),
...defaultSpec,
layout: {
initial: {
isExpanded: false,
@@ -62,6 +63,15 @@ export class AlphaOrbitalsExample {
},
controls: { left: 'none', right: 'none', top: 'none', bottom: 'none' },
},
components: {
viewport: {
canvas3d: {
camera: {
helper: { axes: { name: 'off', params: { } } }
}
}
}
},
config: [
[PluginConfig.Viewport.ShowExpand, false],
[PluginConfig.Viewport.ShowControls, false],

View File

@@ -86,7 +86,7 @@
// adjust this number to make the animation faster or slower
// requires to "restart" the animation if changed
BasicMolStarWrapper.animate.modelIndex.maxFPS = 30;
BasicMolStarWrapper.animate.modelIndex.targetFps = 30;
addControl('Play To End', () => BasicMolStarWrapper.animate.modelIndex.onceForward());
addControl('Play To Start', () => BasicMolStarWrapper.animate.modelIndex.onceBackward());

View File

@@ -83,13 +83,17 @@ class BasicWrapper {
if (!this.plugin.canvas3d.props.trackball.spin) PluginCommands.Camera.Reset(this.plugin, {});
}
private animateModelIndexTargetFps() {
return Math.max(1, this.animate.modelIndex.targetFps | 0);
}
animate = {
modelIndex: {
maxFPS: 8,
onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); },
onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); },
palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); },
loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); },
targetFps: 8,
onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'once', params: { direction: 'forward' } } }); },
onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'once', params: { direction: 'backward' } } }); },
palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'palindrome', params: {} } }); },
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()
}
}

View File

@@ -12,18 +12,18 @@
}
#app {
position: absolute;
left: 160px;
top: 100px;
width: 600px;
height: 600px;
border: 1px solid #ccc;
width: 100%;
height: 100%;
}
#controls {
position: absolute;
width: 150px;
top: 100px;
left: 780px;
bottom: 100px;
right: 50px;
z-index: 10;
font-family: sans-serif;
font-size: smaller;
}
#controls > button {
@@ -46,13 +46,13 @@
<div id="app"></div>
<script>
LightingDemo.init('app')
LightingDemo.load({ url: 'https://files.rcsb.org/download/1M07.cif', assemblyId: '1' })
LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3)
addHeader('Example PDB IDs');
addControl('1M07', () => LightingDemo.load({ url: 'https://files.rcsb.org/download/1M07.cif', assemblyId: '1' }));
addControl('6HY0', () => LightingDemo.load({ url: 'https://files.rcsb.org/download/6HY0.cif', assemblyId: '1' }));
addControl('6QVK', () => LightingDemo.load({ url: 'https://files.rcsb.org/download/6QVK.cif', assemblyId: '1' }));
addControl('1RB8', () => LightingDemo.load({ url: 'https://files.rcsb.org/download/1RB8.cif', assemblyId: '1' }));
addControl('4KTC', () => LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3));
addControl('5FJ5', () => LightingDemo.load({ url: 'https://models.rcsb.org/5FJ5.bcif', assemblyId: '1' }, 8, 1.8));
addControl('1UPN', () => LightingDemo.load({ url: 'https://models.rcsb.org/1UPN.bcif', assemblyId: '1' }, 7, 1.6));
addControl('1RB8', () => LightingDemo.load({ url: 'https://models.rcsb.org/1RB8.bcif', assemblyId: '1' }, 6, 1.3));
addSeparator()

View File

@@ -25,12 +25,11 @@ const Canvas3DPresets = {
mode: 'temporal' as Canvas3DProps['multiSample']['mode']
},
postprocessing: {
occlusion: { name: 'on', params: { samples: 64, radius: 8, bias: 1.0, blurKernelSize: 13 } },
outline: { name: 'on', params: { scale: 1, threshold: 0.33 } }
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } },
outline: { name: 'on', params: { scale: 1, threshold: 0.1 } }
},
renderer: {
ambientIntensity: 1,
lightIntensity: 0,
style: { name: 'flat', params: {} }
}
},
occlusion: <Preset> {
@@ -38,12 +37,11 @@ const Canvas3DPresets = {
mode: 'temporal' as Canvas3DProps['multiSample']['mode']
},
postprocessing: {
occlusion: { name: 'on', params: { samples: 64, radius: 8, bias: 1.0, blurKernelSize: 13 } },
occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } },
outline: { name: 'off', params: { } }
},
renderer: {
ambientIntensity: 0.4,
lightIntensity: 0.6,
style: { name: 'matte', params: {} }
}
},
standard: <Preset> {
@@ -55,17 +53,21 @@ const Canvas3DPresets = {
outline: { name: 'off', params: { } }
},
renderer: {
ambientIntensity: 0.4,
lightIntensity: 0.6,
style: { name: 'matte', params: {} }
}
}
};
type Canvas3DPreset = keyof typeof Canvas3DPresets
class LightingDemo {
plugin: PluginContext;
private radius = 5;
private bias = 1.1;
private preset: Canvas3DPreset = 'illustrative';
init(target: string | HTMLElement) {
this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, {
...DefaultPluginSpec(),
@@ -83,6 +85,10 @@ 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;
}
PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: {
...props,
multiSample: {
@@ -100,7 +106,7 @@ class LightingDemo {
}});
}
async load({ url, format = 'mmcif', isBinary = false, assemblyId = '' }: LoadParams) {
async load({ url, format = 'mmcif', isBinary = true, assemblyId = '' }: LoadParams, radius: number, bias: number) {
await this.plugin.clear();
const data = await this.plugin.builders.data.download({ url: Asset.Url(url), isBinary }, { state: { isGhost: true } });
@@ -112,7 +118,11 @@ class LightingDemo {
if (polymer) await this.plugin.builders.structure.representation.addRepresentation(polymer, { type: 'spacefill', color: 'illustrative' });
const ligand = await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'ligand');
if (ligand) await this.plugin.builders.structure.representation.addRepresentation(ligand, { type: 'ball-and-stick' });
if (ligand) await this.plugin.builders.structure.representation.addRepresentation(ligand, { type: 'ball-and-stick', color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } });
this.radius = radius;
this.bias = bias;
this.setPreset(this.preset);
}
}

View File

@@ -147,7 +147,7 @@
// adjust this number to make the animation faster or slower
// requires to "restart" the animation if changed
PluginWrapper.animate.modelIndex.maxFPS = 30;
PluginWrapper.animate.modelIndex.targetFps = 30;
addControl('Play To End', () => PluginWrapper.animate.modelIndex.onceForward());
addControl('Play To Start', () => PluginWrapper.animate.modelIndex.onceBackward());

View File

@@ -272,13 +272,17 @@ class MolStarProteopediaWrapper {
resetPosition: () => PluginCommands.Camera.Reset(this.plugin, { })
}
private animateModelIndexTargetFps() {
return Math.max(1, this.animate.modelIndex.targetFps | 0);
}
animate = {
modelIndex: {
maxFPS: 8,
onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); },
onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); },
palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); },
loop: () => { this.plugin.managers.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); },
targetFps: 8,
onceForward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'once', params: { direction: 'forward' } } }); },
onceBackward: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'once', params: { direction: 'backward' } } }); },
palindrome: () => { this.plugin.managers.animation.play(AnimateModelIndex, { duration: { name: 'computed', params: { targetFps: this.animateModelIndexTargetFps() } }, mode: { name: 'palindrome', params: {} } }); },
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()
}
}

View File

@@ -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>
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
@@ -100,7 +100,7 @@ export class DrawPass {
}
constructor(private webgl: WebGLContext, width: number, height: number, enableWboit: boolean) {
const { extensions, resources } = webgl;
const { extensions, resources, isWebGL2 } = webgl;
this.drawTarget = createNullRenderTarget(webgl.gl);
@@ -113,8 +113,8 @@ export class DrawPass {
this.depthTargetPrimitives = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
this.depthTargetVolumes = this.packedDepth ? webgl.createRenderTarget(width, height) : null;
this.depthTexturePrimitives = this.depthTargetPrimitives ? this.depthTargetPrimitives.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest');
this.depthTextureVolumes = this.depthTargetVolumes ? this.depthTargetVolumes.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest');
this.depthTexturePrimitives = this.depthTargetPrimitives ? this.depthTargetPrimitives.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest');
this.depthTextureVolumes = this.depthTargetVolumes ? this.depthTargetVolumes.texture : resources.texture('image-depth', 'depth', isWebGL2 ? 'float' : 'ushort', 'nearest');
if (!this.packedDepth) {
this.depthTexturePrimitives.define(width, height);
this.depthTextureVolumes.define(width, height);

View File

@@ -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>
*/
@@ -36,11 +36,36 @@ export interface TextureMesh {
readonly vertexTexture: ValueCell<Texture>,
readonly groupTexture: ValueCell<Texture>,
readonly normalTexture: ValueCell<Texture>,
readonly doubleBuffer: TextureMesh.DoubleBuffer
readonly boundingSphere: Sphere3D
}
export namespace TextureMesh {
export class DoubleBuffer {
private index = 0;
private textures: ({ vertex: Texture, group: Texture, normal: Texture } | undefined)[] = []
get() {
return this.textures[this.index];
}
set(vertex: Texture, group: Texture, normal: Texture) {
this.textures[this.index] = Object.assign(this.textures[this.index] || {}, {
vertex, group, normal
});
this.index = (this.index + 1) % 2;
}
destroy() {
for (const buffer of this.textures) {
buffer!.vertex.destroy();
buffer!.group.destroy();
buffer!.normal.destroy();
}
}
}
export function create(vertexCount: number, groupCount: number, vertexTexture: Texture, groupTexture: Texture, normalTexture: Texture, boundingSphere: Sphere3D, textureMesh?: TextureMesh): TextureMesh {
const width = vertexTexture.getWidth();
const height = vertexTexture.getHeight();
@@ -49,7 +74,9 @@ export namespace TextureMesh {
textureMesh.groupCount = groupCount;
ValueCell.update(textureMesh.geoTextureDim, Vec2.set(textureMesh.geoTextureDim.ref.value, width, height));
ValueCell.update(textureMesh.vertexTexture, vertexTexture);
ValueCell.update(textureMesh.groupTexture, groupTexture);
ValueCell.update(textureMesh.normalTexture, normalTexture);
textureMesh.doubleBuffer.set(vertexTexture, groupTexture, normalTexture);
Sphere3D.copy(textureMesh.boundingSphere, boundingSphere);
return textureMesh;
} else {
@@ -61,6 +88,7 @@ export namespace TextureMesh {
vertexTexture: ValueCell.create(vertexTexture),
groupTexture: ValueCell.create(groupTexture),
normalTexture: ValueCell.create(normalTexture),
doubleBuffer: new DoubleBuffer(),
boundingSphere: Sphere3D.clone(boundingSphere),
};
}

View File

@@ -185,7 +185,7 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
gl.clear(gl.COLOR_BUFFER_BIT);
renderable.render();
gl.flush();
gl.finish();
return { vertexTexture, groupTexture, normalTexture, vertexCount: count };
}

View File

@@ -37,6 +37,7 @@ export function splitValues(schema: RenderableSchema, values: RenderableValues)
const textureValues: TextureValues = {};
const uniformValues: UniformValues = {};
const materialUniformValues: UniformValues = {};
const bufferedUniformValues: UniformValues = {};
Object.keys(schema).forEach(k => {
const spec = schema[k];
if (spec.type === 'attribute') attributeValues[k] = values[k];
@@ -45,11 +46,12 @@ export function splitValues(schema: RenderableSchema, values: RenderableValues)
if (spec.type === 'texture' && values[k] !== undefined) textureValues[k] = values[k];
// check if k exists in values to exclude global uniforms
if (spec.type === 'uniform' && values[k] !== undefined) {
if (spec.isMaterial) materialUniformValues[k] = values[k];
if (spec.variant === 'material') materialUniformValues[k] = values[k];
else if (spec.variant === 'buffered') bufferedUniformValues[k] = values[k];
else uniformValues[k] = values[k];
}
});
return { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues };
return { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues, bufferedUniformValues };
}
export type Versions<T extends RenderableValues> = { [k in keyof T]: number }
@@ -68,9 +70,9 @@ export function AttributeSpec<K extends AttributeKind>(kind: K, itemSize: Attrib
return { type: 'attribute', kind, itemSize, divisor };
}
export type UniformSpec<K extends UniformKind> = { type: 'uniform', kind: K, isMaterial: boolean }
export function UniformSpec<K extends UniformKind>(kind: K, isMaterial = false): UniformSpec<K> {
return { type: 'uniform', kind, isMaterial };
export type UniformSpec<K extends UniformKind> = { type: 'uniform', kind: K, variant?: 'material' | 'buffered' }
export function UniformSpec<K extends UniformKind>(kind: K, variant?: 'material' | 'buffered'): UniformSpec<K> {
return { type: 'uniform', kind, variant };
}
export type TextureSpec<K extends TextureKind> = { type: 'texture', kind: K, format: TextureFormat, dataType: TextureType, filter: TextureFilter }
@@ -180,7 +182,7 @@ export type InternalValues = Values<InternalSchema>
export const ColorSchema = {
// aColor: AttributeSpec('float32', 3, 0), // TODO
uColor: UniformSpec('v3', true),
uColor: UniformSpec('v3', 'material'),
uColorTexDim: UniformSpec('v2'),
tColor: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'),
dColorType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'groupInstance', 'vertex', 'vertexInstance']),
@@ -190,7 +192,7 @@ export type ColorValues = Values<ColorSchema>
export const SizeSchema = {
// aSize: AttributeSpec('float32', 1, 0), // TODO
uSize: UniformSpec('f', true),
uSize: UniformSpec('f', 'material'),
uSizeTexDim: UniformSpec('v2'),
tSize: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'),
dSizeType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'groupInstance']),
@@ -251,7 +253,7 @@ export const BaseSchema = {
/**
* final alpha, calculated as `values.alpha * state.alpha`
*/
uAlpha: UniformSpec('f', true),
uAlpha: UniformSpec('f', 'material'),
uVertexCount: UniformSpec('i'),
uInstanceCount: UniformSpec('i'),
uGroupCount: UniformSpec('i'),

View File

@@ -13,7 +13,7 @@ import { ValueCell } from '../../mol-util';
export const TextureMeshSchema = {
...BaseSchema,
uGeoTexDim: UniformSpec('v2'),
uGeoTexDim: UniformSpec('v2', 'buffered'),
tPosition: TextureSpec('texture', 'rgb', 'float', 'nearest'),
tGroup: TextureSpec('texture', 'alpha', 'float', 'nearest'),
tNormal: TextureSpec('texture', 'rgb', 'float', 'nearest'),

View File

@@ -17,6 +17,8 @@ import { checkFramebufferStatus } from './framebuffer';
import { isDebugMode } from '../../mol-util/debug';
import { VertexArray } from './vertex-array';
import { fillSerial } from '../../mol-util/array';
import { deepClone } from '../../mol-util/object';
import { cloneUniformValues } from './uniform';
const getNextRenderItemId = idFactory();
@@ -123,10 +125,12 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
(schema as any).aVertex = AttributeSpec('float32', 1, 0);
}
const { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues } = splitValues(schema, values);
const { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues, bufferedUniformValues } = splitValues(schema, values);
const uniformValueEntries = Object.entries(uniformValues);
const materialUniformValueEntries = Object.entries(materialUniformValues);
const backBufferUniformValueEntries = Object.entries(bufferedUniformValues);
const frontBufferUniformValueEntries = Object.entries(cloneUniformValues(bufferedUniformValues));
const defineValueEntries = Object.entries(defineValues);
const versions = getValueVersions(values);
@@ -192,6 +196,7 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
currentProgramId = program.id;
}
program.setUniforms(uniformValueEntries);
program.setUniforms(frontBufferUniformValueEntries);
if (sharedTexturesList && sharedTexturesList.length > 0) {
program.bindTextures(sharedTexturesList, 0);
program.bindTextures(textures, sharedTexturesList.length);
@@ -318,11 +323,20 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
if (schema[k].kind !== 'texture') {
// console.log('texture version changed, uploading image', k);
texture.load(value.ref.value as TextureImage<any> | TextureVolume<any>);
versions[k] = value.ref.version;
valueChanges.textures = true;
} else {
textures[i][1] = value.ref.value as Texture;
}
versions[k] = value.ref.version;
}
}
for (let i = 0, il = backBufferUniformValueEntries.length; i < il; ++i) {
const [k, uniform] = backBufferUniformValueEntries[i];
if (uniform.ref.version !== versions[k]) {
// console.log('back-buffer uniform version changed, updating front-buffer', k);
ValueCell.update(frontBufferUniformValueEntries[i][1], deepClone(uniform.ref.value));
versions[k] = uniform.ref.version;
}
}

View File

@@ -8,7 +8,7 @@ import { idFactory } from '../../mol-util/id-factory';
import { createNullTexture, Texture, TextureFilter } from './texture';
import { createNullFramebuffer, Framebuffer } from './framebuffer';
import { WebGLResources } from './resources';
import { GLRenderingContext } from './compat';
import { GLRenderingContext, isWebGL2 } from './compat';
const getNextRenderTargetId = idFactory();
@@ -35,9 +35,11 @@ export function createRenderTarget(gl: GLRenderingContext, resources: WebGLResou
? resources.texture('image-float32', 'rgba', 'float', filter)
: resources.texture('image-uint8', 'rgba', 'ubyte', filter);
// make a depth renderbuffer of the same size as the targetTexture
const depthRenderbuffer = depth
? resources.renderbuffer('depth16', 'depth', _width, _height)
: null;
const depthRenderbuffer = !depth
? null
: isWebGL2(gl)
? resources.renderbuffer('depth32f', 'depth', _width, _height)
: resources.renderbuffer('depth16', 'depth', _width, _height);
function init() {
targetTexture.define(_width, _height);

View File

@@ -1,17 +1,17 @@
/**
* 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>
*/
import { idFactory } from '../../mol-util/id-factory';
import { GLRenderingContext } from './compat';
import { GLRenderingContext, isWebGL2 } from './compat';
import { Framebuffer, checkFramebufferStatus } from './framebuffer';
import { isDebugMode } from '../../mol-util/debug';
const getNextRenderbufferId = idFactory();
export type RenderbufferFormat = 'depth16' | 'stencil8' | 'rgba4' | 'depth-stencil'
export type RenderbufferFormat = 'depth16' | 'stencil8' | 'rgba4' | 'depth-stencil' | 'depth32f'
export type RenderbufferAttachment = 'depth' | 'stencil' | 'depth-stencil' | 'color0'
export function getFormat(gl: GLRenderingContext, format: RenderbufferFormat) {
@@ -20,6 +20,9 @@ export function getFormat(gl: GLRenderingContext, format: RenderbufferFormat) {
case 'stencil8': return gl.STENCIL_INDEX8;
case 'rgba4': return gl.RGBA4;
case 'depth-stencil': return gl.DEPTH_STENCIL;
case 'depth32f':
if (isWebGL2(gl)) return gl.DEPTH_COMPONENT32F;
else throw new Error('WebGL2 needed for `depth32f` renderbuffer format');
}
}

View File

@@ -94,7 +94,10 @@ export function getInternalFormat(gl: GLRenderingContext, format: TextureFormat,
case 'int': return gl.RGBA32I;
}
case 'depth':
return gl.DEPTH_COMPONENT16;
switch (type) {
case 'ushort': return gl.DEPTH_COMPONENT16;
case 'float': return gl.DEPTH_COMPONENT32F;
}
}
}
return getFormat(gl, format, type);
@@ -229,7 +232,7 @@ export function createTexture(gl: GLRenderingContext, extensions: WebGLExtension
(kind.endsWith('float16') && _type !== 'fp16') ||
(kind.endsWith('uint8') && _type !== 'ubyte') ||
(kind.endsWith('int32') && _type !== 'int') ||
(kind.endsWith('depth') && _type !== 'ushort')
(kind.endsWith('depth') && _type !== 'ushort' && _type !== 'float')
) {
throw new Error(`texture kind '${kind}' and type '${_type}' are incompatible`);
}

View File

@@ -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>
*/
@@ -9,6 +9,7 @@ import { ValueCell } from '../../mol-util';
import { GLRenderingContext } from './compat';
import { RenderableSchema } from '../../mol-gl/renderable/schema';
import { ValueOf } from '../../mol-util/type-helpers';
import { deepClone } from '../../mol-util/object';
export type UniformKindValue = {
'b': boolean; 'b[]': boolean[]
@@ -105,4 +106,12 @@ export function isUniformValueScalar(kind: UniformKind): boolean {
default:
return false;
}
}
export function cloneUniformValues(uniformValues: UniformValues): UniformValues {
const clonedValues: UniformValues = {};
Object.keys(uniformValues).forEach(k => {
clonedValues[k] = ValueCell.create(deepClone(uniformValues[k].ref.value));
});
return clonedValues;
}

View File

@@ -58,24 +58,44 @@ async function handleAtoms(state: State, count: number): Promise<PsfFile['atoms'
const charge = TokenBuilder.create(tokenizer.data, count * 2);
const mass = TokenBuilder.create(tokenizer.data, count * 2);
const { position } = tokenizer;
const line = readLine(tokenizer).trim();
tokenizer.position = position;
// LAMMPS full
// AtomID ResID AtomName AtomType Charge Mass Unused0
const isLammpsFull = line.split(reWhitespace).length === 7;
const n = isLammpsFull ? 6 : 8;
const { length } = tokenizer;
let linesAlreadyRead = 0;
await chunkedSubtask(state.runtimeCtx, 10, void 0, chunkSize => {
await chunkedSubtask(state.runtimeCtx, 100000, void 0, chunkSize => {
const linesToRead = Math.min(count - linesAlreadyRead, chunkSize);
for (let i = 0; i < linesToRead; ++i) {
for (let j = 0; j < 8; ++j) {
for (let j = 0; j < n; ++j) {
skipWhitespace(tokenizer);
markStart(tokenizer);
eatValue(tokenizer);
switch (j) {
case 0: TokenBuilder.addUnchecked(atomId, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 1: TokenBuilder.addUnchecked(segmentName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 2: TokenBuilder.addUnchecked(residueId, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 3: TokenBuilder.addUnchecked(residueName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 4: TokenBuilder.addUnchecked(atomName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 5: TokenBuilder.addUnchecked(atomType, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 6: TokenBuilder.addUnchecked(charge, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 7: TokenBuilder.addUnchecked(mass, tokenizer.tokenStart, tokenizer.tokenEnd); break;
if (isLammpsFull) {
switch (j) {
case 0: TokenBuilder.addUnchecked(atomId, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 1: TokenBuilder.addUnchecked(residueId, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 2: TokenBuilder.addUnchecked(atomName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 3: TokenBuilder.addUnchecked(atomType, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 4: TokenBuilder.addUnchecked(charge, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 5: TokenBuilder.addUnchecked(mass, tokenizer.tokenStart, tokenizer.tokenEnd); break;
}
} else {
switch (j) {
case 0: TokenBuilder.addUnchecked(atomId, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 1: TokenBuilder.addUnchecked(segmentName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 2: TokenBuilder.addUnchecked(residueId, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 3: TokenBuilder.addUnchecked(residueName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 4: TokenBuilder.addUnchecked(atomName, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 5: TokenBuilder.addUnchecked(atomType, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 6: TokenBuilder.addUnchecked(charge, tokenizer.tokenStart, tokenizer.tokenEnd); break;
case 7: TokenBuilder.addUnchecked(mass, tokenizer.tokenStart, tokenizer.tokenEnd); break;
}
}
}
// ignore any extra columns
@@ -89,9 +109,13 @@ async function handleAtoms(state: State, count: number): Promise<PsfFile['atoms'
return {
count,
atomId: TokenColumn(atomId)(Column.Schema.int),
segmentName: TokenColumn(segmentName)(Column.Schema.str),
segmentName: isLammpsFull
? TokenColumn(residueId)(Column.Schema.str)
: TokenColumn(segmentName)(Column.Schema.str),
residueId: TokenColumn(residueId)(Column.Schema.int),
residueName: TokenColumn(residueName)(Column.Schema.str),
residueName: isLammpsFull
? TokenColumn(residueId)(Column.Schema.str)
: TokenColumn(residueName)(Column.Schema.str),
atomName: TokenColumn(atomName)(Column.Schema.str),
atomType: TokenColumn(atomType)(Column.Schema.str),
charge: TokenColumn(charge)(Column.Schema.float),

View File

@@ -0,0 +1,71 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Column } from '../../../mol-data/db';
import { Task } from '../../../mol-task';
import { Tokenizer } from '../common/text/tokenizer';
import { ReaderResult as Result } from '../result';
export interface XyzFile {
readonly molecules: {
readonly comment: string,
readonly count: number,
readonly x: Column<number>,
readonly y: Column<number>,
readonly z: Column<number>,
readonly type_symbol: Column<string>
}[],
}
function handleMolecule(tokenizer: Tokenizer): XyzFile['molecules'][number] {
let count = tokenizer.position >= tokenizer.data.length - 1 ? 0 : +Tokenizer.readLine(tokenizer);
if (isNaN(count)) count = 0;
const comment = Tokenizer.readLine(tokenizer);
const x = new Float64Array(count);
const y = new Float64Array(count);
const z = new Float64Array(count);
const type_symbol = new Array<string>(count);
for (let i = 0; i < count; ++i) {
const line = Tokenizer.readLine(tokenizer);
const fields = line.split(/\s+/g);
type_symbol[i] = fields[0];
x[i] = +fields[1];
y[i] = +fields[2];
z[i] = +fields[3];
}
return {
count,
comment,
x: Column.ofFloatArray(x),
y: Column.ofFloatArray(y),
z: Column.ofFloatArray(z),
type_symbol: Column.ofStringArray(type_symbol)
};
}
function parseInternal(data: string): Result<XyzFile> {
const tokenizer = Tokenizer(data);
const molecules: XyzFile['molecules'] = [];
while (true) {
const mol = handleMolecule(tokenizer);
if (mol.count === 0) break;
molecules.push(mol);
}
const result: XyzFile = { molecules };
return Result.success(result);
}
export function parseXyz(data: string) {
return Task.create<Result<XyzFile>>('Parse Mol', async () => {
return parseInternal(data);
});
}

View File

@@ -33,14 +33,14 @@ export const GaussianDensitySchema = {
uCurrentSlice: UniformSpec('f'),
uCurrentX: UniformSpec('f'),
uCurrentY: UniformSpec('f'),
uBboxMin: UniformSpec('v3', true),
uBboxSize: UniformSpec('v3', true),
uGridDim: UniformSpec('v3', true),
uGridTexDim: UniformSpec('v3', true),
uGridTexScale: UniformSpec('v2', true),
uAlpha: UniformSpec('f', true),
uResolution: UniformSpec('f', true),
uRadiusFactorInv: UniformSpec('f', true),
uBboxMin: UniformSpec('v3', 'material'),
uBboxSize: UniformSpec('v3', 'material'),
uGridDim: UniformSpec('v3', 'material'),
uGridTexDim: UniformSpec('v3', 'material'),
uGridTexScale: UniformSpec('v2', 'material'),
uAlpha: UniformSpec('f', 'material'),
uResolution: UniformSpec('f', 'material'),
uRadiusFactorInv: UniformSpec('f', 'material'),
tMinDistanceTex: TextureSpec('texture', 'rgba', 'float', 'nearest'),
dGridTexType: DefineSpec('string', ['2d', '3d']),

View File

@@ -50,6 +50,7 @@ const StandardComponents = (function() {
{ id: 'ASP', name: 'ASPARTIC ACID', type: 'L-peptide linking' },
{ id: 'GLU', name: 'GLUTAMIC ACID', type: 'L-peptide linking' },
{ id: 'THR', name: 'THREONINE', type: 'L-peptide linking' },
{ id: 'PRO', name: 'PROLINE', type: 'L-peptide linking' },
{ id: 'SEC', name: 'SELENOCYSTEINE', type: 'L-peptide linking' },
{ id: 'PYL', name: 'PYRROLYSINE', type: 'L-peptide linking' },

View File

@@ -0,0 +1,108 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Column, Table } from '../../mol-data/db';
import { XyzFile } from '../../mol-io/reader/xyz/parser';
import { Trajectory } from '../../mol-model/structure';
import { MoleculeType } from '../../mol-model/structure/model/types';
import { RuntimeContext, Task } from '../../mol-task';
import { ModelFormat } from '../format';
import { createModels } from './basic/parser';
import { BasicSchema, createBasic } from './basic/schema';
import { ComponentBuilder } from './common/component';
import { EntityBuilder } from './common/entity';
function getModels(mol: XyzFile, ctx: RuntimeContext) {
const { molecules } = mol;
let count = 0;
for (const m of molecules) count += m.count;
const type_symbols = new Array<string>(count);
const id = new Int32Array(count);
const x = new Float32Array(count);
const y = new Float32Array(count);
const z = new Float32Array(count);
const model_num = new Int32Array(count);
let offset = 0;
for (let i = 0; i < molecules.length; i++) {
const m = molecules[i];
for (let j = 0; j < m.count; j++) {
type_symbols[offset] = m.type_symbol.value(j);
x[offset] = m.x.value(j);
y[offset] = m.y.value(j);
z[offset] = m.z.value(j);
id[offset] = j;
model_num[offset] = i;
offset++;
}
}
const MOL = Column.ofConst('MOL', count, Column.Schema.str);
const A = Column.ofConst('A', count, Column.Schema.str);
const seq_id = Column.ofConst(1, count, Column.Schema.int);
const type_symbol = Column.ofStringArray(type_symbols);
const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, {
auth_asym_id: A,
auth_atom_id: type_symbol,
auth_comp_id: MOL,
auth_seq_id: seq_id,
Cartn_x: Column.ofFloatArray(x),
Cartn_y: Column.ofFloatArray(y),
Cartn_z: Column.ofFloatArray(z),
id: Column.ofIntArray(id),
label_asym_id: A,
label_atom_id: type_symbol,
label_comp_id: MOL,
label_seq_id: seq_id,
label_entity_id: Column.ofConst('1', count, Column.Schema.str),
occupancy: Column.ofConst(1, count, Column.Schema.float),
type_symbol,
pdbx_PDB_model_num: Column.ofIntArray(model_num),
}, count);
const entityBuilder = new EntityBuilder();
entityBuilder.setNames([['MOL', 'Unknown Entity']]);
entityBuilder.getEntityId('MOL', MoleculeType.Unknown, 'A');
const componentBuilder = new ComponentBuilder(seq_id, type_symbol);
componentBuilder.setNames([['MOL', 'Unknown Molecule']]);
componentBuilder.add('MOL', 0);
const basics = createBasic({
entity: entityBuilder.getEntityTable(),
chem_comp: componentBuilder.getChemCompTable(),
atom_site
});
return createModels(basics, MolFormat.create(mol), ctx);
}
//
export { XyzFormat };
type XyzFormat = ModelFormat<XyzFile>
namespace MolFormat {
export function is(x?: ModelFormat): x is XyzFormat {
return x?.kind === 'mol';
}
export function create(mol: XyzFile): XyzFormat {
return { kind: 'xyz', name: 'xyz', data: mol };
}
}
export function trajectoryFromXyz(mol: XyzFile): Task<Trajectory> {
return Task.create('Parse XYZ', ctx => getModels(mol, ctx));
}

View File

@@ -28,7 +28,7 @@ export const InteractionsProvider: CustomStructureProperty.Provider<Interactions
type: 'local',
defaultParams: InteractionsParams,
getParams: (data: Structure) => InteractionsParams,
isApplicable: (data: Structure) => true,
isApplicable: (data: Structure) => !data.isCoarseGrained,
obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<InteractionsProps>) => {
const p = { ...PD.getDefaultValues(InteractionsParams), ...props };
return { value: await computeInteractions(ctx, data, p) };

View File

@@ -46,7 +46,7 @@ export const InteractionsRepresentationProvider = StructureRepresentationProvide
defaultValues: PD.getDefaultValues(InteractionsParams),
defaultColorTheme: { name: 'interaction-type' },
defaultSizeTheme: { name: 'uniform' },
isApplicable: (structure: Structure) => structure.elementCount > 0,
isApplicable: (structure: Structure) => structure.elementCount > 0 && InteractionsProvider.isApplicable(structure),
ensureCustomProperties: {
attach: (ctx: CustomProperty.Context, structure: Structure) => InteractionsProvider.attach(ctx, structure, void 0, true),
detach: (data) => InteractionsProvider.ref(data, false)

View File

@@ -1,5 +1,5 @@
/**
* 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 David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -29,6 +29,7 @@ import { CustomModelProperty } from '../../../mol-model-props/common/custom-mode
import { Trajectory, ArrayTrajectory } from '../trajectory';
import { Unit } from '../structure';
import { SortedArray } from '../../../mol-data/int/sorted-array';
import { PolymerType } from './types';
/**
* Interface to the "source data" of the molecule.
@@ -119,6 +120,8 @@ export namespace Model {
ModelSymmetry.Provider.set(m, symmetry);
}
TrajectoryInfo.set(m, { index: i, size: frames.length });
trajectory.push(m);
}
return { trajectory, srcIndexArray };
@@ -222,6 +225,39 @@ export namespace Model {
}
};
const CoarseGrainedProp = '__CoarseGrained__';
/**
* Has typical coarse grained atom names (BB, SC1) or less than twice as many
* atoms as polymer residues (C-alpha only models).
*/
export function isCoarseGrained(model: Model): boolean {
if (model._staticPropertyData[CoarseGrainedProp] !== undefined) return model._staticPropertyData[CoarseGrainedProp];
let polymerResidueCount = 0;
const { polymerType } = model.atomicHierarchy.derived.residue;
for (let i = 0; i < polymerType.length; ++i) {
if (polymerType[i] !== PolymerType.NA) polymerResidueCount += 1;
}
// check for coarse grained atom names
let hasBB = false, hasSC1 = false;
const { label_atom_id, _rowCount: atomCount } = model.atomicHierarchy.atoms;
for (let i = 0; i < atomCount; ++i) {
const atomName = label_atom_id.value(i);
if (!hasBB && atomName === 'BB') hasBB = true;
if (!hasSC1 && atomName === 'SC1') hasSC1 = true;
if (hasBB && hasSC1) break;
}
const coarseGrained = (hasBB && hasSC1) || (
polymerResidueCount && atomCount
? atomCount / polymerResidueCount < 2
: false
);
model._staticPropertyData[CoarseGrainedProp] = coarseGrained;
return coarseGrained;
}
//
export function hasCarbohydrate(model: Model): boolean {

View File

@@ -306,10 +306,11 @@ export interface IncludeConnectedParams {
query: StructureQuery,
bondTest?: QueryFn<boolean>,
layerCount: number,
wholeResidues: boolean
wholeResidues: boolean,
fixedPoint: boolean
}
export function includeConnected({ query, layerCount, wholeResidues, bondTest }: IncludeConnectedParams): StructureQuery {
export function includeConnected({ query, layerCount, wholeResidues, bondTest, fixedPoint }: IncludeConnectedParams): StructureQuery {
const lc = Math.max(layerCount, 0);
return function query_includeConnected(ctx) {
const builder = StructureSelection.UniqueBuilder(ctx.inputStructure);
@@ -318,8 +319,17 @@ export function includeConnected({ query, layerCount, wholeResidues, bondTest }:
ctx.atomicBond.setTestFn(bondTest);
StructureSelection.forEach(src, (s, sI) => {
let incl = s;
for (let i = 0; i < lc; i++) {
incl = includeConnectedStep(ctx, wholeResidues, incl);
if (fixedPoint) {
while (true) {
const prevCount = incl.elementCount;
incl = includeConnectedStep(ctx, wholeResidues, incl);
if (incl.elementCount === prevCount) break;
}
} else {
for (let i = 0; i < lc; i++) {
incl = includeConnectedStep(ctx, wholeResidues, incl);
}
}
builder.add(incl);
if (sI % 10 === 0) ctx.throwIfTimedOut();

View File

@@ -5,6 +5,6 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import * as StructureElement from './element/index';
import * as StructureElement from './element/element';
export { StructureElement };

View File

@@ -5,50 +5,8 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { SortedArray } from '../../../../mol-data/int';
import { ElementIndex, ResidueIndex, ChainIndex } from '../../model';
import { Unit } from '../unit';
import { Location } from './location';
import { StructureProperties } from '../properties';
// TODO: when nominal types are available, make this indexed by UnitIndex
export type Set = SortedArray<ElementIndex>
/** Index into Unit.elements */
export type UnitIndex = { readonly '@type': 'unit-element-index' } & number
export interface Property<T> { (location: Location): T }
export interface Predicate extends Property<boolean> { }
export function property<T>(p: Property<T>) { return p; }
function _wrongUnitKind(kind: string) { throw new Error(`Property only available for ${kind} models.`); }
export function atomicProperty<T>(p: (location: Location<Unit.Atomic>) => T) {
return property(l => Unit.isAtomic(l.unit) ? p(l as Location<Unit.Atomic>) : _wrongUnitKind('atomic'));
}
export function coarseProperty<T>(p: (location: Location<Unit.Spheres | Unit.Gaussians>) => T) {
return property(l => Unit.isCoarse(l.unit) ? p(l as Location<Unit.Spheres | Unit.Gaussians>) : _wrongUnitKind('coarse'));
}
export function residueIndex(e: Location) {
if (Unit.isAtomic(e.unit)) {
return e.unit.residueIndex[e.element];
} else {
// TODO: throw error instead?
return -1 as ResidueIndex;
}
}
export function chainIndex(e: Location) {
if (Unit.isAtomic(e.unit)) {
return e.unit.chainIndex[e.element];
} else {
// TODO: throw error instead?
return -1 as ChainIndex;
}
}
export function entityIndex(l: Location) {
return StructureProperties.entity.key(l);
}
export * from './location';
export * from './loci';
export * from './bundle';
export * from './stats';
export * from './util';

View File

@@ -1,12 +0,0 @@
/**
* Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
export * from './location';
export * from './loci';
export * from './bundle';
export * from './stats';
export * from './element';

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { SortedArray } from '../../../../mol-data/int';
import { ElementIndex, ResidueIndex, ChainIndex } from '../../model';
import { Unit } from '../unit';
import { Location } from './location';
import { StructureProperties } from '../properties';
// TODO: when nominal types are available, make this indexed by UnitIndex
export type Set = SortedArray<ElementIndex>
/** Index into Unit.elements */
export type UnitIndex = { readonly '@type': 'unit-element-index' } & number
export interface Property<T> { (location: Location): T }
export interface Predicate extends Property<boolean> { }
export function property<T>(p: Property<T>) { return p; }
function _wrongUnitKind(kind: string) { throw new Error(`Property only available for ${kind} models.`); }
export function atomicProperty<T>(p: (location: Location<Unit.Atomic>) => T) {
return property(l => Unit.isAtomic(l.unit) ? p(l as Location<Unit.Atomic>) : _wrongUnitKind('atomic'));
}
export function coarseProperty<T>(p: (location: Location<Unit.Spheres | Unit.Gaussians>) => T) {
return property(l => Unit.isCoarse(l.unit) ? p(l as Location<Unit.Spheres | Unit.Gaussians>) : _wrongUnitKind('coarse'));
}
export function residueIndex(e: Location) {
if (Unit.isAtomic(e.unit)) {
return e.unit.residueIndex[e.element];
} else {
// TODO: throw error instead?
return -1 as ResidueIndex;
}
}
export function chainIndex(e: Location) {
if (Unit.isAtomic(e.unit)) {
return e.unit.chainIndex[e.element];
} else {
// TODO: throw error instead?
return -1 as ChainIndex;
}
}
export function entityIndex(l: Location) {
return StructureProperties.entity.key(l);
}

View File

@@ -158,13 +158,11 @@ class Structure {
}
/**
* Coarse-grained structure, defined as containing less than
* twice as many elements as polymer residues
* True if any model the structure is based on is coarse grained.
* @see Model.isCoarseGrained
*/
get isCoarseGrained() {
const ec = this.elementCount;
const prc = this.polymerResidueCount;
return prc && ec ? ec / prc < 2 : false;
return this.models.some(m => Model.isCoarseGrained(m));
}
get isEmpty() {
@@ -299,7 +297,7 @@ class Structure {
/** Contains only atomic units */
get isAtomic() {
for (const u of this.units) if (Unit.isAtomic(u)) return false;
for (const u of this.units) if (!Unit.isAtomic(u)) return false;
return true;
}
@@ -311,7 +309,7 @@ class Structure {
/** Contains only coarse units */
get isCoarse() {
for (const u of this.units) if (Unit.isCoarse(u)) return false;
for (const u of this.units) if (!Unit.isCoarse(u)) return false;
return true;
}

View File

@@ -153,7 +153,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
? thresholdAB
: beI < 0
? thresholdA
: (thresholdA + getElementThreshold(beI)) / 2; // not sure if avg or min but max is too big
: (thresholdA + getElementThreshold(beI)) / 1.95; // not sure if avg or min but max is too big
if (dist <= pairingThreshold) {
const atomIdB = label_atom_idB.value(bI);
@@ -176,7 +176,7 @@ export interface InterBondComputationProps extends BondComputationProps {
function findBonds(structure: Structure, props: InterBondComputationProps) {
const builder = new InterUnitGraph.Builder<number, StructureElement.UnitIndex, InterUnitEdgeProps>();
if (props.noCompute) {
if (props.noCompute || structure.isCoarseGrained) {
// TODO add function that only adds bonds defined in structConn and avoids using
// structure.lookup and unit.lookup (expensive for large structure and not
// needed for archival files or files with an MD topology)

View File

@@ -19,6 +19,7 @@ import { StructConn } from '../../../../../mol-model-formats/structure/property/
import { Vec3 } from '../../../../../mol-math/linear-algebra';
import { ElementIndex } from '../../../model/indexing';
import { equalEps } from '../../../../../mol-math/linear-algebra/3d/common';
import { Model } from '../../../model/model';
function getGraph(atomA: StructureElement.UnitIndex[], atomB: StructureElement.UnitIndex[], _order: number[], _flags: number[], atomCount: number, canRemap: boolean): IntraUnitBonds {
const builder = new IntAdjacencyGraph.EdgeBuilder(atomCount, atomA, atomB);
@@ -211,7 +212,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
? thresholdAB
: beI < 0
? thresholdA
: (thresholdA + getElementThreshold(beI)) / 2; // not sure if avg or min but max is too big
: (thresholdA + getElementThreshold(beI)) / 1.95; // not sure if avg or min but max is too big
if (dist <= pairingThreshold) {
atomA[atomA.length] = _aI;
@@ -233,7 +234,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
function computeIntraUnitBonds(unit: Unit.Atomic, props?: Partial<BondComputationProps>) {
const p = { ...DefaultBondComputationProps, ...props };
if (p.noCompute) {
if (p.noCompute || Model.isCoarseGrained(unit.model)) {
// TODO add function that only adds bonds defined in structConn of chemCompBond
// and avoid using unit.lookup
return IntraUnitBonds.Empty;

View File

@@ -14,13 +14,24 @@ import { PluginStateAnimation } from '../model';
export const AnimateModelIndex = PluginStateAnimation.create({
name: 'built-in.animate-model-index',
display: { name: 'Animate Trajectory' },
isExportable: true,
params: () => ({
mode: PD.MappedStatic('palindrome', {
mode: PD.MappedStatic('loop', {
palindrome: PD.Group({ }),
loop: PD.Group({ }),
loop: PD.Group({ direction: PD.Select('forward', [['forward', 'Forward'], ['backward', 'Backward']]) }),
once: PD.Group({ direction: PD.Select('forward', [['forward', 'Forward'], ['backward', 'Backward']]) }, { isFlat: true })
}, { options: [['palindrome', 'Palindrome'], ['loop', 'Loop'], ['once', 'Once']] }),
maxFPS: PD.Numeric(15, { min: 1, max: 60, step: 1 })
duration: PD.MappedStatic('fixed', {
fixed: PD.Group({
durationInS: PD.Numeric(5, { min: 1, max: 120, step: 0.1 }, { description: 'Duration in seconds' })
}, { isFlat: true }),
computed: PD.Group({
targetFps: PD.Numeric(30, { min: 5, max: 250, step: 1 }, { label: 'Target FPS' })
}, { isFlat: true }),
sequential: PD.Group({
maxFps: PD.Numeric(30, { min: 5, max: 60, step: 1 })
}, { isFlat: true })
})
}),
canApply(ctx) {
const state = ctx.state.data;
@@ -31,10 +42,30 @@ export const AnimateModelIndex = PluginStateAnimation.create({
}
return { canApply: false, reason: 'No trajectory to animate' };
},
getDuration: (p, ctx) => {
if (p.duration?.name === 'fixed') {
return { kind: 'fixed', durationMs: p.duration.params.durationInS * 1000 };
} else if (p.duration.name === 'computed') {
const state = ctx.state.data;
const models = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Model.ModelFromTrajectory));
let maxDuration = 0;
for (const m of models) {
const parent = StateSelection.findAncestorOfType(state.tree, state.cells, m.transform.ref, PluginStateObject.Molecule.Trajectory);
if (!parent || !parent.obj) continue;
const traj = parent.obj;
maxDuration = Math.max(Math.ceil(1000 * traj.data.frameCount / p.duration.params.targetFps), maxDuration);
}
return { kind: 'fixed', durationMs: maxDuration };
}
return { kind: 'unknown' };
},
initialState: () => ({} as { palindromeDirections?: { [id: string]: -1 | 1 | undefined } }),
async apply(animState, t, ctx) {
// limit fps
if (t.current > 0 && t.current - t.lastApplied < 1000 / ctx.params.maxFPS) {
if (ctx.params.duration.name === 'sequential' && t.current > 0 && t.current - t.lastApplied < 1000 / ctx.params.duration.params.maxFps) {
return { kind: 'skip' };
}
@@ -65,27 +96,48 @@ export const AnimateModelIndex = PluginStateAnimation.create({
} else {
return old;
}
let dir: -1 | 1 = 1;
if (params.mode.name === 'once') {
dir = params.mode.params.direction === 'backward' ? -1 : 1;
// if we are at start or end already, do nothing.
if ((dir === -1 && old.modelIndex === 0) || (dir === 1 && old.modelIndex === len - 1)) {
isEnd = true;
return old;
if (params.duration.name === 'sequential') {
let dir: -1 | 1 = 1;
if (params.mode.name === 'once') {
dir = params.mode.params.direction === 'backward' ? -1 : 1;
// if we are at start or end already, do nothing.
if ((dir === -1 && old.modelIndex === 0) || (dir === 1 && old.modelIndex === len - 1)) {
isEnd = true;
return old;
}
} else if (params.mode.name === 'palindrome') {
if (old.modelIndex === 0) dir = 1;
else if (old.modelIndex === len - 1) dir = -1;
else dir = palindromeDirections[m.transform.ref] || 1;
}
} else if (params.mode.name === 'palindrome') {
if (old.modelIndex === 0) dir = 1;
else if (old.modelIndex === len - 1) dir = -1;
else dir = palindromeDirections[m.transform.ref] || 1;
palindromeDirections[m.transform.ref] = dir;
let modelIndex = (old.modelIndex + dir) % len;
if (modelIndex < 0) modelIndex += len;
isEnd = isEnd || (dir === -1 && modelIndex === 0) || (dir === 1 && modelIndex === len - 1);
return { modelIndex };
} else {
const durationInMs = params.duration.name === 'fixed'
? params.duration.params.durationInS * 1000
: Math.ceil(1000 * traj.data.frameCount / params.duration.params.targetFps);
let phase: number = (t.current % durationInMs) / durationInMs;
if (params.mode.name === 'loop') {
if (params.mode.params.direction === 'backward') {
phase = 1 - phase;
}
} if (params.mode.name === 'palindrome') {
phase = 2 * phase;
if (phase > 1) phase = 2 - phase;
}
const modelIndex = Math.min(Math.floor(traj.data.frameCount * phase), traj.data.frameCount - 1);
isEnd = isEnd || modelIndex === traj.data.frameCount - 1;
return { modelIndex };
}
palindromeDirections[m.transform.ref] = dir;
let modelIndex = (old.modelIndex + dir) % len;
if (modelIndex < 0) modelIndex += len;
isEnd = isEnd || (dir === -1 && modelIndex === 0) || (dir === 1 && modelIndex === len - 1);
return { modelIndex };
});
}

View File

@@ -22,6 +22,7 @@ import { ChainIdColorThemeProvider } from '../../../mol-theme/color/chain-id';
import { OperatorNameColorThemeProvider } from '../../../mol-theme/color/operator-name';
import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bonds/index-pair';
import { StructConn } from '../../../mol-model-formats/structure/property/bonds/struct_conn';
import { StructureRepresentationRegistry } from '../../../mol-repr/structure/registry';
export interface StructureRepresentationPresetProvider<P = any, S extends _Result = _Result> extends PresetProvider<PluginStateObject.Molecule.Structure, P, S> { }
export function StructureRepresentationPresetProvider<P, S extends _Result>(repr: StructureRepresentationPresetProvider<P, S>) { return repr; }
@@ -230,7 +231,7 @@ const coarseSurface = StructureRepresentationPresetProvider({
id: 'preset-structure-representation-coarse-surface',
display: {
name: 'Coarse Surface', group: BuiltInPresetGroupName,
description: 'Shows polymers as coarse Gaussian Surface.'
description: 'Shows polymers and lipids as coarse Gaussian Surface.'
},
params: () => CommonParams,
async apply(ref, params, plugin) {
@@ -238,7 +239,8 @@ const coarseSurface = StructureRepresentationPresetProvider({
if (!structureCell) return {};
const components = {
polymer: await presetStaticComponent(plugin, structureCell, 'polymer')
polymer: await presetStaticComponent(plugin, structureCell, 'polymer'),
lipid: await presetStaticComponent(plugin, structureCell, 'lipid'),
};
const structure = structureCell.obj!.data;
@@ -246,7 +248,7 @@ const coarseSurface = StructureRepresentationPresetProvider({
const gaussianProps = Object.create(null);
if (size === Structure.Size.Gigantic) {
Object.assign(gaussianProps, {
traceOnly: true,
traceOnly: !structure.isCoarseGrained,
radiusOffset: 2,
smoothness: 1,
visuals: ['structure-gaussian-surface-mesh']
@@ -266,7 +268,8 @@ const coarseSurface = StructureRepresentationPresetProvider({
const { update, builder, typeParams, symmetryColor } = reprBuilder(plugin, params, structure);
const representations = {
polymer: builder.buildRepresentation(update, components.polymer, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor }, { tag: 'polymer' })
polymer: builder.buildRepresentation(update, components.polymer, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor }, { tag: 'polymer' }),
lipid: builder.buildRepresentation(update, components.lipid, { type: 'gaussian-surface', typeParams: { ...typeParams, ...gaussianProps }, color: symmetryColor }, { tag: 'lipid' })
};
await update.commit({ revertOnError: true });
@@ -337,9 +340,15 @@ const atomicDetail = StructureRepresentationPresetProvider({
const m = structure.models[0];
const bondsGiven = !!IndexPairBonds.Provider.get(m) || StructConn.isExhaustive(m);
const atomicType = lowResidueElementRatio && !bondsGiven
? 'spacefill' : highElementCount
? 'line' : 'ball-and-stick';
let atomicType: StructureRepresentationRegistry.BuiltIn = 'ball-and-stick';
if (structure.isCoarseGrained) {
// TODO make configurable?
atomicType = structure.elementCount > 1_000_000 ? 'point' : 'spacefill';
} else if (lowResidueElementRatio && !bondsGiven) {
atomicType = 'spacefill';
} else if (highElementCount) {
atomicType = 'line';
}
const showCarbohydrateSymbol = params.showCarbohydrateSymbol && !highElementCount && !lowResidueElementRatio;
if (showCarbohydrateSymbol) {

View File

@@ -103,6 +103,15 @@ export const PdbqtProvider: TrajectoryFormatProvider = {
visuals: defaultVisuals
};
export const XyzProvider: TrajectoryFormatProvider = {
label: 'XYZ',
description: 'XYZ',
category: TrajectoryFormatCategory,
stringExtensions: ['xyz'],
parse: directTrajectory(StateTransforms.Model.TrajectoryFromXYZ),
visuals: defaultVisuals
};
export const GroProvider: TrajectoryFormatProvider = {
label: 'GRO',
description: 'GRO',
@@ -137,6 +146,7 @@ export const BuiltInTrajectoryFormats = [
['pdb', PdbProvider] as const,
['pdbqt', PdbqtProvider] as const,
['gro', GroProvider] as const,
['xyz', XyzProvider] as const,
['mol', MolProvider] as const,
['mol2', Mol2Provider] as const,
] as const;

View File

@@ -446,6 +446,16 @@ const covalentlyBonded = StructureSelectionQuery('Residues Covalently Bonded to
referencesCurrent: true
});
const covalentlyBondedComponent = StructureSelectionQuery('Covalently Bonded Component', MS.struct.modifier.union([
MS.struct.modifier.includeConnected({
0: MS.internal.generator.current(), 'fixed-point': true
})
]), {
description: 'Select covalently bonded component based on current selection.',
category: StructureSelectionCategory.Manipulate,
referencesCurrent: true
});
const covalentlyOrMetallicBonded = StructureSelectionQuery('Residues with Cov. or Metallic Bond to Selection', MS.struct.modifier.union([
MS.struct.modifier.includeConnected({
0: MS.internal.generator.current(),
@@ -638,6 +648,7 @@ export const StructureSelectionQueries = {
complement,
covalentlyBonded,
covalentlyOrMetallicBonded,
covalentlyBondedComponent,
wholeResidues,
};

View File

@@ -37,6 +37,8 @@ import { parseMol2 } from '../../mol-io/reader/mol2/parser';
import { trajectoryFromMol2 } from '../../mol-model-formats/structure/mol2';
import { parseXtc } from '../../mol-io/reader/xtc/parser';
import { coordinatesFromXtc } from '../../mol-model-formats/structure/xtc';
import { parseXyz } from '../../mol-io/reader/xyz/parser';
import { trajectoryFromXyz } from '../../mol-model-formats/structure/xyz';
export { CoordinatesFromDcd };
export { CoordinatesFromXtc };
@@ -46,6 +48,7 @@ export { TrajectoryFromBlob };
export { TrajectoryFromMmCif };
export { TrajectoryFromPDB };
export { TrajectoryFromGRO };
export { TrajectoryFromXYZ };
export { TrajectoryFromMOL };
export { TrajectoryFromMOL2 };
export { TrajectoryFromCube };
@@ -253,6 +256,24 @@ const TrajectoryFromGRO = PluginStateTransform.BuiltIn({
}
});
type TrajectoryFromXYZ = typeof TrajectoryFromXYZ
const TrajectoryFromXYZ = PluginStateTransform.BuiltIn({
name: 'trajectory-from-xyz',
display: { name: 'Parse XYZ', description: 'Parse XYZ string and create trajectory.' },
from: [SO.Data.String],
to: SO.Molecule.Trajectory
})({
apply({ a }) {
return Task.create('Parse XYZ', async ctx => {
const parsed = await parseXyz(a.data).runInContext(ctx);
if (parsed.isError) throw new Error(parsed.message);
const models = await trajectoryFromXyz(parsed.result).runInContext(ctx);
const props = trajectoryProps(models);
return new SO.Molecule.Trajectory(models, props);
});
}
});
type TrajectoryFromMOL = typeof TrajectoryFromMOL
const TrajectoryFromMOL = PluginStateTransform.BuiltIn({
name: 'trajectory-from-mol',
@@ -345,9 +366,9 @@ const ModelFromTrajectory = PluginStateTransform.BuiltIn({
to: SO.Molecule.Model,
params: a => {
if (!a) {
return { modelIndex: PD.Numeric(0, {}, { description: 'Zero-based index of the model' }) };
return { modelIndex: PD.Numeric(0, {}, { description: 'Zero-based index of the model', immediateUpdate: true }) };
}
return { modelIndex: PD.Converted(plus1, minus1, PD.Numeric(1, { min: 1, max: a.data.frameCount, step: 1 }, { description: 'Model Index' })) };
return { modelIndex: PD.Converted(plus1, minus1, PD.Numeric(1, { min: 1, max: a.data.frameCount, step: 1 }, { description: 'Model Index', immediateUpdate: true })) };
}
})({
isApplicable: a => a.data.frameCount > 0,

View File

@@ -383,10 +383,10 @@ export class SequenceView extends PluginUIComponent<{ defaultMode?: SequenceView
if (values.mode === 'single') return elem;
return <>
return <React.Fragment key={i}>
<div className='msp-sequence-chain-label'>{s.label}</div>
{elem}
</>;
</React.Fragment>;
})}
</NonEmptySequenceWrapper>
</div>;

View File

@@ -1,23 +1,23 @@
/**
* 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 David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import * as React from 'react';
import { StructureHierarchyRef, ModelRef, TrajectoryRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
import { Model } from '../../mol-model/structure';
import { ModelRef, StructureHierarchyRef, TrajectoryRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
import { StateTransforms } from '../../mol-plugin-state/transforms';
import { StateSelection } from '../../mol-state';
import { CollapsableControls, CollapsableState } from '../base';
import { ActionMenu } from '../controls/action-menu';
import { Button, IconButton, ExpandGroup } from '../controls/common';
import { Button, ExpandGroup, IconButton } from '../controls/common';
import { BookmarksOutlinedSvg, MoleculeSvg } from '../controls/icons';
import { ParameterControls } from '../controls/parameters';
import { StructureFocusControls } from './focus';
import { UpdateTransformControl } from '../state/update-transform';
import { StructureFocusControls } from './focus';
import { StructureSelectionStatsControls } from './selection';
import { StateSelection } from '../../mol-state';
import { MoleculeSvg, BookmarksOutlinedSvg } from '../controls/icons';
import { Model } from '../../mol-model/structure';
interface StructureSourceControlState extends CollapsableState {
isBusy: boolean,
@@ -214,13 +214,30 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo
mng.hierarchy.applyPreset(trajectories, item.value as any);
}
updateStructureModel = async (params: any) => {
const { selection } = this.plugin.managers.structure.hierarchy;
const m = selection.structures[0].model!;
this.plugin.state.updateTransform(this.plugin.state.data, m.cell.transform.ref, params, 'Model Index');
// TODO: ?? PluginCommands.Camera.Reset(this.plugin);
private updateModelQueueParams: any = void 0;
private isUpdatingModel = false;
private async _updateStructureModel() {
if (!this.updateModelQueueParams || this.isUpdatingModel) return;
const params = this.updateModelQueueParams;
this.updateModelQueueParams = void 0;
try {
this.isUpdatingModel = true;
const { selection } = this.plugin.managers.structure.hierarchy;
const m = selection.structures[0].model!;
await this.plugin.state.updateTransform(this.plugin.state.data, m.cell.transform.ref, params, 'Model Index');
} finally {
this.isUpdatingModel = false;
this._updateStructureModel();
}
}
updateStructureModel = (params: any) => {
this.updateModelQueueParams = params;
this._updateStructureModel();
};
get modelIndex() {
const { selection } = this.plugin.managers.structure.hierarchy;
if (selection.structures.length !== 1) return null;

View File

@@ -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 David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -107,7 +107,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
.apply(StateTransforms.Representation.StructureRepresentation3D, this.getReprParams(this.params.surroundingsParams), { tags: StructureFocusRepresentationTags.SurrRepr }).ref;
}
if (components.indexOf('interactions') >= 0 && !refs[StructureFocusRepresentationTags.SurrNciRepr]) {
if (components.indexOf('interactions') >= 0 && !refs[StructureFocusRepresentationTags.SurrNciRepr] && cell.obj && InteractionsRepresentationProvider.isApplicable(cell.obj?.data)) {
refs[StructureFocusRepresentationTags.SurrNciRepr] = builder
.to(refs[StructureFocusRepresentationTags.SurrSel]!)
.apply(StateTransforms.Representation.StructureRepresentation3D, this.params.nciParams, { tags: StructureFocusRepresentationTags.SurrNciRepr }).ref;

View File

@@ -21,7 +21,11 @@ export const SpacefillParams = {
};
export type SpacefillParams = typeof SpacefillParams
export function getSpacefillParams(ctx: ThemeRegistryContext, structure: Structure) {
return PD.clone(SpacefillParams);
const params = PD.clone(SpacefillParams);
if (structure.isCoarseGrained) {
params.sizeFactor.defaultValue = 2;
}
return params;
}
export type SpacefillRepresentation = StructureRepresentation<SpacefillParams>

View File

@@ -18,8 +18,7 @@ import { Sphere3D } from '../../../mol-math/geometry';
export const ElementPointParams = {
...UnitsPointsParams,
// sizeFactor: PD.Numeric(1.0, { min: 0, max: 10, step: 0.01 }),
pointSizeAttenuation: PD.Boolean(false),
pointSizeAttenuation: PD.Boolean(true),
ignoreHydrogens: PD.Boolean(false),
traceOnly: PD.Boolean(false),
};

View File

@@ -181,7 +181,8 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit,
const isoLevel = Math.exp(-props.smoothness) / densityTextureData.radiusFactor;
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, true, textureMesh?.vertexTexture.ref.value, textureMesh?.groupTexture.ref.value, textureMesh?.normalTexture.ref.value);
const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, true, buffer?.vertex, buffer?.group, buffer?.normal);
const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
@@ -211,6 +212,7 @@ export function GaussianSurfaceTextureMeshVisual(materialId: number): UnitsVisua
geometry.vertexTexture.ref.value.destroy();
geometry.groupTexture.ref.value.destroy();
geometry.normalTexture.ref.value.destroy();
geometry.doubleBuffer.destroy();
}
}, materialId);
}
@@ -238,7 +240,8 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str
const isoLevel = Math.exp(-props.smoothness) / densityTextureData.radiusFactor;
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, true, textureMesh?.vertexTexture.ref.value, textureMesh?.groupTexture.ref.value, textureMesh?.normalTexture.ref.value);
const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, true, buffer?.vertex, buffer?.group, buffer?.normal);
const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
@@ -267,6 +270,7 @@ export function StructureGaussianSurfaceTextureMeshVisual(materialId: number): C
geometry.vertexTexture.ref.value.destroy();
geometry.groupTexture.ref.value.destroy();
geometry.normalTexture.ref.value.destroy();
geometry.doubleBuffer.destroy();
}
}, materialId);
}

View File

@@ -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>
* @author David Sehnal <david.sehnal@gmail.com>
@@ -23,6 +23,9 @@ import { SpheresBuilder } from '../../../../mol-geo/geometry/spheres/spheres-bui
import { isTrace, isH } from './common';
import { Sphere3D } from '../../../../mol-math/geometry';
// avoiding namespace lookup improved performance in Chrome (Aug 2020)
const v3add = Vec3.add;
type ElementProps = {
ignoreHydrogens: boolean,
traceOnly: boolean,
@@ -59,27 +62,38 @@ export function createElementSphereMesh(ctx: VisualContext, unit: Unit, structur
const v = Vec3();
const pos = unit.conformation.invariantPosition;
const ignore = makeElementIgnoreTest(unit, props);
const l = StructureElement.Location.create(structure);
l.unit = unit;
const l = StructureElement.Location.create(structure, unit);
const themeSize = theme.size.size;
const center = Vec3();
let maxSize = 0;
let count = 0;
for (let i = 0; i < elementCount; i++) {
if (ignore && ignore(unit, elements[i])) continue;
l.element = elements[i];
pos(elements[i], v);
v3add(center, center, v);
count += 1;
builderState.currentGroup = i;
const size = theme.size.size(l);
const size = themeSize(l);
if (size > maxSize) maxSize = size;
addSphere(builderState, v, size * sizeFactor, detail);
}
// re-use boundingSphere if it has not changed much
let boundingSphere: Sphere3D;
Vec3.scale(center, center, 1 / count);
if (mesh && Vec3.distance(center, mesh.boundingSphere.center) / mesh.boundingSphere.radius < 1.0) {
boundingSphere = Sphere3D.clone(mesh.boundingSphere);
} else {
boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxSize * sizeFactor + 0.05);
}
const m = MeshBuilder.getMesh(builderState);
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxSize * sizeFactor + 0.05);
m.setBoundingSphere(sphere);
m.setBoundingSphere(boundingSphere);
return m;
}
@@ -98,21 +112,35 @@ export function createElementSphereImpostor(ctx: VisualContext, unit: Unit, stru
const ignore = makeElementIgnoreTest(unit, props);
const l = StructureElement.Location.create(structure, unit);
const themeSize = theme.size.size;
const center = Vec3();
let maxSize = 0;
let count = 0;
for (let i = 0; i < elementCount; i++) {
if (ignore?.(unit, elements[i])) continue;
pos(elements[i], v);
builder.add(v[0], v[1], v[2], i);
v3add(center, center, v);
count += 1;
l.element = elements[i];
const size = theme.size.size(l);
const size = themeSize(l);
if (size > maxSize) maxSize = size;
}
// re-use boundingSphere if it has not changed much
let boundingSphere: Sphere3D;
Vec3.scale(center, center, 1 / count);
if (spheres && Vec3.distance(center, spheres.boundingSphere.center) / spheres.boundingSphere.radius < 1.0) {
boundingSphere = Sphere3D.clone(spheres.boundingSphere);
} else {
boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxSize * props.sizeFactor + 0.05);
}
const s = builder.getSpheres();
s.setBoundingSphere(Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxSize * props.sizeFactor + 0.05));
s.setBoundingSphere(boundingSphere);
return s;
}

View File

@@ -175,7 +175,8 @@ async function createVolumeIsosurfaceTextureMesh(ctx: VisualContext, volume: Vol
const { texture, gridDimension, gridTexDim, gridTexScale, transform } = VolumeIsosurfaceTexture.get(volume, ctx.webgl);
const gv = extractIsosurface(ctx.webgl, texture, gridDimension, gridTexDim, gridTexScale, transform, isoLevel, false, textureMesh?.vertexTexture.ref.value, textureMesh?.groupTexture.ref.value, textureMesh?.normalTexture.ref.value);
const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, texture, gridDimension, gridTexDim, gridTexScale, transform, isoLevel, false, buffer?.vertex, buffer?.group, buffer?.normal);
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, Volume.getBoundingSphere(volume), textureMesh);
@@ -200,6 +201,7 @@ export function IsosurfaceTextureMeshVisual(materialId: number): VolumeVisual<Is
geometry.vertexTexture.ref.value.destroy();
geometry.groupTexture.ref.value.destroy();
geometry.normalTexture.ref.value.destroy();
geometry.doubleBuffer.destroy();
}
}, materialId);
}

View File

@@ -159,6 +159,7 @@ const modifier = {
0: Argument(Types.ElementSelectionQuery),
'bond-test': Argument(Type.Bool, { isOptional: true, defaultValue: 'true for covalent bonds' as any }),
'layer-count': Argument(Type.Num, { isOptional: true, defaultValue: 1, description: 'Number of bonded layers to include.' }),
'fixed-point': Argument(Type.Bool, { isOptional: true, defaultValue: false, description: 'Continue adding layers as long as new connections exist.' }),
'as-whole-residues': Argument(Type.Bool, { isOptional: true })
}), Types.ElementSelectionQuery, 'Pick all atom sets that are connected to the target.'),

View File

@@ -267,7 +267,8 @@ const symbols = [
query: xs[0] as any,
bondTest: xs['bond-test'],
wholeResidues: !!(xs['as-whole-residues'] && xs['as-whole-residues'](ctx)),
layerCount: (xs['layer-count'] && xs['layer-count'](ctx)) || 1
layerCount: (xs['layer-count'] && xs['layer-count'](ctx)) || 1,
fixedPoint: xs['fixed-point']?.(ctx) ?? false
})(ctx);
}),

View File

@@ -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>
*/
@@ -33,6 +33,8 @@ import { OccupancyColorThemeProvider } from './color/occupancy';
import { OperatorNameColorThemeProvider } from './color/operator-name';
import { OperatorHklColorThemeProvider } from './color/operator-hkl';
import { PartialChargeColorThemeProvider } from './color/partial-charge';
import { AtomIdColorThemeProvider } from './color/atom-id';
import { EntityIdColorThemeProvider } from './color/entity-id';
export type LocationColor = (location: Location, isSecondary: boolean) => Color
@@ -80,10 +82,12 @@ namespace ColorTheme {
}
export const BuiltIn = {
'atom-id': AtomIdColorThemeProvider,
'carbohydrate-symbol': CarbohydrateSymbolColorThemeProvider,
'chain-id': ChainIdColorThemeProvider,
'element-index': ElementIndexColorThemeProvider,
'element-symbol': ElementSymbolColorThemeProvider,
'entity-id': EntityIdColorThemeProvider,
'entity-source': EntitySourceColorThemeProvider,
'hydrophobicity': HydrophobicityColorThemeProvider,
'illustrative': IllustrativeColorThemeProvider,

View File

@@ -0,0 +1,90 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { StructureProperties, StructureElement, Bond, Structure } from '../../mol-model/structure';
import { Color } from '../../mol-util/color';
import { Location } from '../../mol-model/location';
import { ColorTheme, LocationColor } from '../color';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { ThemeDataContext } from '../../mol-theme/theme';
import { getPaletteParams, getPalette } from '../../mol-util/color/palette';
import { TableLegend, ScaleLegend } from '../../mol-util/legend';
const DefaultList = 'many-distinct';
const DefaultColor = Color(0xFAFAFA);
const Description = 'Gives every atom a color based on its `label_atom_id` value.';
export const AtomIdColorThemeParams = {
...getPaletteParams({ type: 'colors', colorList: DefaultList }),
};
export type AtomIdColorThemeParams = typeof AtomIdColorThemeParams
export function getAtomIdColorThemeParams(ctx: ThemeDataContext) {
const params = PD.clone(AtomIdColorThemeParams);
return params;
}
function getAtomIdSerialMap(structure: Structure) {
const map = new Map<string, number>();
for (const m of structure.models) {
const { label_atom_id } = m.atomicHierarchy.atoms;
for (let i = 0, il = label_atom_id.rowCount; i < il; ++i) {
const id = label_atom_id.value(i);
if (!map.has(id)) map.set(id, map.size);
}
}
return map;
}
export function AtomIdColorTheme(ctx: ThemeDataContext, props: PD.Values<AtomIdColorThemeParams>): ColorTheme<AtomIdColorThemeParams> {
let color: LocationColor;
let legend: ScaleLegend | TableLegend | undefined;
if (ctx.structure) {
const l = StructureElement.Location.create(ctx.structure.root);
const atomIdSerialMap = getAtomIdSerialMap(ctx.structure.root);
const labelTable = Array.from(atomIdSerialMap.keys());
const valueLabel = (i: number) => labelTable[i];
const palette = getPalette(atomIdSerialMap.size, props, { valueLabel });
legend = palette.legend;
color = (location: Location): Color => {
let serial: number | undefined = undefined;
if (StructureElement.Location.is(location)) {
const id = StructureProperties.atom.label_atom_id(location);
serial = atomIdSerialMap.get(id);
} else if (Bond.isLocation(location)) {
l.unit = location.aUnit;
l.element = location.aUnit.elements[location.aIndex];
const id = StructureProperties.atom.label_atom_id(l);
serial = atomIdSerialMap.get(id);
}
return serial === undefined ? DefaultColor : palette.color(serial);
};
} else {
color = () => DefaultColor;
}
return {
factory: AtomIdColorTheme,
granularity: 'group',
color,
props,
description: Description,
legend
};
}
export const AtomIdColorThemeProvider: ColorTheme.Provider<AtomIdColorThemeParams, 'atom-id'> = {
name: 'atom-id',
label: 'Atom Id',
category: ColorTheme.Category.Atom,
factory: AtomIdColorTheme,
getParams: getAtomIdColorThemeParams,
defaultValues: PD.getDefaultValues(AtomIdColorThemeParams),
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
};

View File

@@ -0,0 +1,98 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { StructureProperties, StructureElement, Bond, Structure } from '../../mol-model/structure';
import { Color } from '../../mol-util/color';
import { Location } from '../../mol-model/location';
import { ColorTheme, LocationColor } from '../color';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { ThemeDataContext } from '../../mol-theme/theme';
import { getPaletteParams, getPalette } from '../../mol-util/color/palette';
import { TableLegend, ScaleLegend } from '../../mol-util/legend';
const DefaultList = 'many-distinct';
const DefaultColor = Color(0xFAFAFA);
const Description = 'Gives every chain a color based on its `label_entity_id` value.';
export const EntityIdColorThemeParams = {
...getPaletteParams({ type: 'colors', colorList: DefaultList }),
};
export type EntityIdColorThemeParams = typeof EntityIdColorThemeParams
export function getEntityIdColorThemeParams(ctx: ThemeDataContext) {
const params = PD.clone(EntityIdColorThemeParams);
return params;
}
function key(entityId: string, modelIndex: number) {
return `${entityId}|${modelIndex}`;
}
function getEntityIdSerialMap(structure: Structure) {
const map = new Map<string, number>();
for (let i = 0, il = structure.models.length; i < il; ++i) {
const { label_entity_id } = structure.models[i].atomicHierarchy.chains;
for (let j = 0, jl = label_entity_id.rowCount; j < jl; ++j) {
const k = key(label_entity_id.value(j), i);
if (!map.has(k)) map.set(k, map.size);
}
}
return map;
}
export function EntityIdColorTheme(ctx: ThemeDataContext, props: PD.Values<EntityIdColorThemeParams>): ColorTheme<EntityIdColorThemeParams> {
let color: LocationColor;
let legend: ScaleLegend | TableLegend | undefined;
if (ctx.structure) {
const l = StructureElement.Location.create(ctx.structure.root);
const entityIdSerialMap = getEntityIdSerialMap(ctx.structure.root);
const labelTable = Array.from(entityIdSerialMap.keys());
const valueLabel = (i: number) => labelTable[i];
const palette = getPalette(entityIdSerialMap.size, props, { valueLabel });
legend = palette.legend;
color = (location: Location): Color => {
let serial: number | undefined = undefined;
if (StructureElement.Location.is(location)) {
const atomId = StructureProperties.chain.label_entity_id(location);
const modelIndex = location.structure.models.indexOf(location.unit.model);
const k = key(atomId, modelIndex);
serial = entityIdSerialMap.get(k);
} else if (Bond.isLocation(location)) {
l.unit = location.aUnit;
l.element = location.aUnit.elements[location.aIndex];
const atomId = StructureProperties.chain.label_entity_id(l);
const modelIndex = l.structure.models.indexOf(l.unit.model);
const k = key(atomId, modelIndex);
serial = entityIdSerialMap.get(k);
}
return serial === undefined ? DefaultColor : palette.color(serial);
};
} else {
color = () => DefaultColor;
}
return {
factory: EntityIdColorTheme,
granularity: 'group',
color,
props,
description: Description,
legend
};
}
export const EntityIdColorThemeProvider: ColorTheme.Provider<EntityIdColorThemeParams, 'entity-id'> = {
name: 'entity-id',
label: 'Entity Id',
category: ColorTheme.Category.Chain,
factory: EntityIdColorTheme,
getParams: getEntityIdColorThemeParams,
defaultValues: PD.getDefaultValues(EntityIdColorThemeParams),
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
};