mirror of
https://github.com/molstar/molstar.git
synced 2026-06-04 21:34:23 +08:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bec644997 | ||
|
|
650d38dff8 | ||
|
|
097277e397 | ||
|
|
82a4d5eedf | ||
|
|
2a00248812 | ||
|
|
9841c773cb | ||
|
|
b21a78ad14 | ||
|
|
7329fa597d | ||
|
|
f1d8f0ecb4 | ||
|
|
1d127f2364 | ||
|
|
b244405cc3 | ||
|
|
38adfe0ca6 | ||
|
|
6f0d798847 | ||
|
|
6e58bfd2b0 | ||
|
|
bc2e8d8ac4 | ||
|
|
7be654d47f | ||
|
|
bfe46e3604 | ||
|
|
008b597fc5 | ||
|
|
c4b4f2e3b1 | ||
|
|
76ee97301b | ||
|
|
289dc09eae | ||
|
|
f23f84f0f3 | ||
|
|
62259f3295 | ||
|
|
854a430a12 | ||
|
|
d27cdb5637 | ||
|
|
7d12d9ee90 | ||
|
|
d70a4ff347 | ||
|
|
49541558d1 | ||
|
|
7b00a1227c | ||
|
|
7800603c81 | ||
|
|
fca00c8116 | ||
|
|
00fa549e44 | ||
|
|
36181b6b87 | ||
|
|
88a95162e9 | ||
|
|
9c1d59a2c8 | ||
|
|
fdd894956a | ||
|
|
eb6dc0859d | ||
|
|
b99026bba2 | ||
|
|
6fa50eb8d5 | ||
|
|
e5046f15a9 | ||
|
|
09f1c066a0 | ||
|
|
ed2f0b34c9 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -6,6 +6,26 @@ Note that since we don't clearly distinguish between a public and private interf
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v3.2.0] - 2022-02-17
|
||||
|
||||
- Rename "best database mapping" to "SIFTS Mapping"
|
||||
- Add schema and export support for ``atom_site.pdbx_sifts_xref_*`` fields
|
||||
- Add schema export support for ``atom_site.pdbx_label_index`` field
|
||||
- Add `traceOnly` parameter to chain/UniProt-based structure alignment
|
||||
- Store ``IndexPairBonds`` as a dynamic property.
|
||||
|
||||
## [v3.1.0] - 2022-02-06
|
||||
|
||||
- Fix ``xrayShaded`` & ``ignoreLight`` params not working at the same time
|
||||
- Add ``ignoreLight`` to component params
|
||||
- Tweaks for cleaner default representation style
|
||||
- Cartoon: use ``nucleotide-ring`` instead of ``nucleotide-block``
|
||||
- Focus: use ``xrayShaded`` instead of opacity; adjust target size; don't show non-covalent interactions twice
|
||||
- Fix representation preset side effects (changing post-processing parameters, see #363)
|
||||
- Add Quick Styles panel (default, illustrative, stylized)
|
||||
- Fix exported structure missing secondary-structure categories (#364)
|
||||
- Fix volume streaming error message: distinguish between missing data and server error (#364)
|
||||
|
||||
## [v3.0.2] - 2022-01-30
|
||||
|
||||
- Fix color smoothing of elongated structures (by fixing ``Sphere.expand`` for spheres with highly directional extrema)
|
||||
|
||||
@@ -24,6 +24,11 @@ atom_site.auth_asym_id
|
||||
atom_site.auth_seq_id
|
||||
atom_site.pdbx_PDB_model_num
|
||||
atom_site.ihm_model_id
|
||||
atom_site.pdbx_label_index
|
||||
atom_site.pdbx_sifts_xref_db_name
|
||||
atom_site.pdbx_sifts_xref_db_acc
|
||||
atom_site.pdbx_sifts_xref_db_num
|
||||
atom_site.pdbx_sifts_xref_db_res
|
||||
|
||||
atom_site_anisotrop.id
|
||||
atom_site_anisotrop.U
|
||||
|
||||
|
1816
package-lock.json
generated
1816
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
38
package.json
38
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
@@ -92,50 +92,50 @@
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/add": "^3.1.1",
|
||||
"@graphql-codegen/cli": "^2.4.0",
|
||||
"@graphql-codegen/cli": "^2.5.0",
|
||||
"@graphql-codegen/time": "^3.1.1",
|
||||
"@graphql-codegen/typescript": "^2.4.2",
|
||||
"@graphql-codegen/typescript": "^2.4.3",
|
||||
"@graphql-codegen/typescript-graphql-files-modules": "^2.1.1",
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.3.3",
|
||||
"@graphql-codegen/typescript-operations": "^2.2.2",
|
||||
"@graphql-codegen/typescript-graphql-request": "^4.3.4",
|
||||
"@graphql-codegen/typescript-operations": "^2.2.4",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/gl": "^4.1.0",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^5.10.2",
|
||||
"benchmark": "^2.1.4",
|
||||
"concurrently": "^7.0.0",
|
||||
"cpx2": "^4.1.2",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"eslint": "^8.7.0",
|
||||
"css-loader": "^6.6.0",
|
||||
"eslint": "^8.8.0",
|
||||
"extra-watch-webpack-plugin": "^1.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"graphql": "^16.2.0",
|
||||
"graphql": "^16.3.0",
|
||||
"http-server": "^14.1.0",
|
||||
"jest": "^27.4.7",
|
||||
"mini-css-extract-plugin": "^2.5.2",
|
||||
"jest": "^27.5.0",
|
||||
"mini-css-extract-plugin": "^2.5.3",
|
||||
"path-browserify": "^1.0.1",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sass": "^1.49.0",
|
||||
"sass": "^1.49.7",
|
||||
"sass-loader": "^12.4.0",
|
||||
"simple-git": "^2.48.0",
|
||||
"simple-git": "^3.1.1",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.5.5",
|
||||
"webpack": "^5.67.0",
|
||||
"webpack-cli": "^4.9.1"
|
||||
"webpack": "^5.68.0",
|
||||
"webpack-cli": "^4.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/argparse": "^2.0.10",
|
||||
"@types/benchmark": "^2.1.1",
|
||||
"@types/compression": "1.7.2",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/node": "^16.11.21",
|
||||
"@types/node": "^16.11.22",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"@types/react": "^17.0.38",
|
||||
"@types/react": "^17.0.39",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@types/swagger-ui-dist": "3.30.1",
|
||||
"argparse": "^2.0.1",
|
||||
@@ -148,7 +148,7 @@
|
||||
"immutable": "^4.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"rxjs": "^7.5.2",
|
||||
"swagger-ui-dist": "^4.2.1",
|
||||
"swagger-ui-dist": "^4.5.0",
|
||||
"tslib": "^2.3.1",
|
||||
"util.promisify": "^1.1.1",
|
||||
"xhr2": "^0.2.1"
|
||||
|
||||
@@ -4,7 +4,7 @@ export type InputMaybe<T> = Maybe<T>;
|
||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
|
||||
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
|
||||
// Generated on 2022-01-15T19:52:34-08:00
|
||||
// Generated on 2022-02-06T15:40:15-08:00
|
||||
|
||||
/** All built-in and custom scalars, mapped to their actual values */
|
||||
export type Scalars = {
|
||||
@@ -13145,4 +13145,4 @@ export type AssemblySymmetryQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type AssemblySymmetryQuery = { readonly assembly?: { readonly rcsb_struct_symmetry?: ReadonlyArray<{ readonly kind: string, readonly oligomeric_state: string, readonly stoichiometry: ReadonlyArray<string | null | undefined>, readonly symbol: string, readonly type: string, readonly clusters: ReadonlyArray<{ readonly avg_rmsd?: number | null | undefined, readonly members: ReadonlyArray<{ readonly asym_id: string, readonly pdbx_struct_oper_list_ids?: ReadonlyArray<string | null | undefined> | null | undefined } | null | undefined> } | null | undefined>, readonly rotation_axes?: ReadonlyArray<{ readonly order?: number | null | undefined, readonly start: ReadonlyArray<number | null | undefined>, readonly end: ReadonlyArray<number | null | undefined> } | null | undefined> | null | undefined } | null | undefined> | null | undefined } | null | undefined };
|
||||
export type AssemblySymmetryQuery = { readonly assembly?: { readonly rcsb_struct_symmetry?: ReadonlyArray<{ readonly kind: string, readonly oligomeric_state: string, readonly stoichiometry: ReadonlyArray<string | null>, readonly symbol: string, readonly type: string, readonly clusters: ReadonlyArray<{ readonly avg_rmsd?: number | null, readonly members: ReadonlyArray<{ readonly asym_id: string, readonly pdbx_struct_oper_list_ids?: ReadonlyArray<string | null> | null } | null> } | null>, readonly rotation_axes?: ReadonlyArray<{ readonly order?: number | null, readonly start: ReadonlyArray<number | null>, readonly end: ReadonlyArray<number | null> } | null> | null } | null> | null } | null };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*
|
||||
@@ -8,61 +8,65 @@
|
||||
*/
|
||||
|
||||
export const apply_light_color = `
|
||||
#ifdef bumpEnabled
|
||||
if (uBumpFrequency > 0.0 && uBumpAmplitude > 0.0) {
|
||||
vec3 bumpNormal = perturbNormal(-vViewPosition, normal, fbm(vModelPosition * uBumpFrequency), (uBumpAmplitude * bumpiness) / uBumpFrequency);
|
||||
#ifdef enabledFragDepth
|
||||
if (!isNaN(bumpNormal.x) && !isNaN(bumpNormal.y) && !isNaN(bumpNormal.z)) {
|
||||
normal = bumpNormal;
|
||||
}
|
||||
#else
|
||||
normal = bumpNormal;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 color = material;
|
||||
|
||||
ReflectedLight reflectedLight = ReflectedLight(vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
|
||||
PhysicalMaterial physicalMaterial;
|
||||
physicalMaterial.diffuseColor = color.rgb * (1.0 - metalness);
|
||||
#ifdef enabledFragDepth
|
||||
physicalMaterial.roughness = min(max(roughness, 0.0525), 1.0);
|
||||
#ifdef dIgnoreLight
|
||||
gl_FragColor = material;
|
||||
#else
|
||||
vec3 dxy = max(abs(dFdx(normal)), abs(dFdy(normal)));
|
||||
float geometryRoughness = max(max(dxy.x, dxy.y), dxy.z);
|
||||
physicalMaterial.roughness = min(max(roughness, 0.0525) + geometryRoughness, 1.0);
|
||||
#ifdef bumpEnabled
|
||||
if (uBumpFrequency > 0.0 && uBumpAmplitude > 0.0) {
|
||||
vec3 bumpNormal = perturbNormal(-vViewPosition, normal, fbm(vModelPosition * uBumpFrequency), (uBumpAmplitude * bumpiness) / uBumpFrequency);
|
||||
#ifdef enabledFragDepth
|
||||
if (!isNaN(bumpNormal.x) && !isNaN(bumpNormal.y) && !isNaN(bumpNormal.z)) {
|
||||
normal = bumpNormal;
|
||||
}
|
||||
#else
|
||||
normal = bumpNormal;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 color = material;
|
||||
|
||||
ReflectedLight reflectedLight = ReflectedLight(vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
|
||||
PhysicalMaterial physicalMaterial;
|
||||
physicalMaterial.diffuseColor = color.rgb * (1.0 - metalness);
|
||||
#ifdef enabledFragDepth
|
||||
physicalMaterial.roughness = min(max(roughness, 0.0525), 1.0);
|
||||
#else
|
||||
vec3 dxy = max(abs(dFdx(normal)), abs(dFdy(normal)));
|
||||
float geometryRoughness = max(max(dxy.x, dxy.y), dxy.z);
|
||||
physicalMaterial.roughness = min(max(roughness, 0.0525) + geometryRoughness, 1.0);
|
||||
#endif
|
||||
physicalMaterial.specularColor = mix(vec3(0.04), color.rgb, metalness);
|
||||
physicalMaterial.specularF90 = 1.0;
|
||||
|
||||
GeometricContext geometry;
|
||||
geometry.position = -vViewPosition;
|
||||
geometry.normal = normal;
|
||||
geometry.viewDir = normalize(vViewPosition);
|
||||
|
||||
IncidentLight directLight;
|
||||
#pragma unroll_loop_start
|
||||
for (int i = 0; i < dLightCount; ++i) {
|
||||
directLight.direction = uLightDirection[i];
|
||||
directLight.color = uLightColor[i] * PI; // * PI for punctual light
|
||||
RE_Direct_Physical(directLight, geometry, physicalMaterial, reflectedLight);
|
||||
}
|
||||
#pragma unroll_loop_end
|
||||
|
||||
vec3 irradiance = uAmbientColor * PI; // * PI for punctual light
|
||||
RE_IndirectDiffuse_Physical(irradiance, geometry, physicalMaterial, reflectedLight);
|
||||
|
||||
// indirect specular only metals
|
||||
vec3 radiance = uAmbientColor * metalness;
|
||||
vec3 iblIrradiance = uAmbientColor * metalness;
|
||||
vec3 clearcoatRadiance = vec3(0.0);
|
||||
RE_IndirectSpecular_Physical(radiance, iblIrradiance, clearcoatRadiance, geometry, physicalMaterial, reflectedLight);
|
||||
|
||||
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;
|
||||
|
||||
gl_FragColor = vec4(outgoingLight, color.a);
|
||||
#endif
|
||||
physicalMaterial.specularColor = mix(vec3(0.04), color.rgb, metalness);
|
||||
physicalMaterial.specularF90 = 1.0;
|
||||
|
||||
GeometricContext geometry;
|
||||
geometry.position = -vViewPosition;
|
||||
geometry.normal = normal;
|
||||
geometry.viewDir = normalize(vViewPosition);
|
||||
|
||||
IncidentLight directLight;
|
||||
#pragma unroll_loop_start
|
||||
for (int i = 0; i < dLightCount; ++i) {
|
||||
directLight.direction = uLightDirection[i];
|
||||
directLight.color = uLightColor[i] * PI; // * PI for punctual light
|
||||
RE_Direct_Physical(directLight, geometry, physicalMaterial, reflectedLight);
|
||||
}
|
||||
#pragma unroll_loop_end
|
||||
|
||||
vec3 irradiance = uAmbientColor * PI; // * PI for punctual light
|
||||
RE_IndirectDiffuse_Physical(irradiance, geometry, physicalMaterial, reflectedLight);
|
||||
|
||||
// indirect specular only metals
|
||||
vec3 radiance = uAmbientColor * metalness;
|
||||
vec3 iblIrradiance = uAmbientColor * metalness;
|
||||
vec3 clearcoatRadiance = vec3(0.0);
|
||||
RE_IndirectSpecular_Physical(radiance, iblIrradiance, clearcoatRadiance, geometry, physicalMaterial, reflectedLight);
|
||||
|
||||
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;
|
||||
|
||||
gl_FragColor = vec4(outgoingLight, color.a);
|
||||
|
||||
#ifdef dXrayShaded
|
||||
gl_FragColor.a *= 1.0 - pow(abs(dot(normal, vec3(0.0, 0.0, 1.0))), uXrayEdgeFalloff);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -127,13 +127,9 @@ void main() {
|
||||
#elif defined(dRenderVariant_marking)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_color)
|
||||
#ifdef dIgnoreLight
|
||||
gl_FragColor = material;
|
||||
#else
|
||||
mat3 normalMatrix = transpose3(inverse3(mat3(uView)));
|
||||
vec3 normal = normalize(normalMatrix * -normalize(intersection.yzw));
|
||||
#include apply_light_color
|
||||
#endif
|
||||
mat3 normalMatrix = transpose3(inverse3(mat3(uView)));
|
||||
vec3 normal = normalize(normalMatrix * -normalize(intersection.yzw));
|
||||
#include apply_light_color
|
||||
|
||||
#include apply_interior_color
|
||||
#include apply_marker_color
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Michael Krone <michael.krone@uni-tuebingen.de>
|
||||
@@ -166,9 +166,7 @@ vec3 v3m4(vec3 p, mat4 m) {
|
||||
float preFogAlphaBlended = 0.0;
|
||||
|
||||
vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
#if !defined(dIgnoreLight)
|
||||
mat3 normalMatrix = transpose3(inverse3(mat3(uModelView * vTransform)));
|
||||
#endif
|
||||
mat3 normalMatrix = transpose3(inverse3(mat3(uModelView * vTransform)));
|
||||
mat4 cartnToUnit = uCartnToUnit * inverse4(vTransform);
|
||||
#if defined(dClipVariant_pixel) && dClipObjectCount != 0
|
||||
mat4 modelTransform = uModel * vTransform * uTransform;
|
||||
@@ -296,24 +294,20 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
|
||||
material.rgb = mix(material.rgb, overpaint.rgb, overpaint.a);
|
||||
#endif
|
||||
|
||||
#ifdef dIgnoreLight
|
||||
if (material.a >= 0.01) {
|
||||
#ifdef dPackedGroup
|
||||
// compute gradient by central differences
|
||||
gradient.x = textureVal(unitPos - dx).a - textureVal(unitPos + dx).a;
|
||||
gradient.y = textureVal(unitPos - dy).a - textureVal(unitPos + dy).a;
|
||||
gradient.z = textureVal(unitPos - dz).a - textureVal(unitPos + dz).a;
|
||||
#else
|
||||
gradient = cell.xyz * 2.0 - 1.0;
|
||||
#endif
|
||||
vec3 normal = -normalize(normalMatrix * normalize(gradient));
|
||||
#include apply_light_color
|
||||
} else {
|
||||
gl_FragColor.rgb = material.rgb;
|
||||
#else
|
||||
if (material.a >= 0.01) {
|
||||
#ifdef dPackedGroup
|
||||
// compute gradient by central differences
|
||||
gradient.x = textureVal(unitPos - dx).a - textureVal(unitPos + dx).a;
|
||||
gradient.y = textureVal(unitPos - dy).a - textureVal(unitPos + dy).a;
|
||||
gradient.z = textureVal(unitPos - dz).a - textureVal(unitPos + dz).a;
|
||||
#else
|
||||
gradient = cell.xyz * 2.0 - 1.0;
|
||||
#endif
|
||||
vec3 normal = -normalize(normalMatrix * normalize(gradient));
|
||||
#include apply_light_color
|
||||
} else {
|
||||
gl_FragColor.rgb = material.rgb;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gl_FragColor.a = material.a * uAlpha * uTransferScale;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -43,17 +43,13 @@ void main() {
|
||||
#elif defined(dRenderVariant_marking)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_color)
|
||||
#ifdef dIgnoreLight
|
||||
gl_FragColor = material;
|
||||
#if defined(dFlatShaded)
|
||||
vec3 normal = -faceNormal;
|
||||
#else
|
||||
#if defined(dFlatShaded)
|
||||
vec3 normal = -faceNormal;
|
||||
#else
|
||||
vec3 normal = -normalize(vNormal);
|
||||
if (uDoubleSided) normal *= float(frontFacing) * 2.0 - 1.0;
|
||||
#endif
|
||||
#include apply_light_color
|
||||
vec3 normal = -normalize(vNormal);
|
||||
if (uDoubleSided) normal *= float(frontFacing) * 2.0 - 1.0;
|
||||
#endif
|
||||
#include apply_light_color
|
||||
|
||||
#include apply_interior_color
|
||||
#include apply_marker_color
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -92,12 +92,8 @@ void main(void){
|
||||
#elif defined(dRenderVariant_marking)
|
||||
gl_FragColor = material;
|
||||
#elif defined(dRenderVariant_color)
|
||||
#ifdef dIgnoreLight
|
||||
gl_FragColor = material;
|
||||
#else
|
||||
vec3 normal = -cameraNormal;
|
||||
#include apply_light_color
|
||||
#endif
|
||||
vec3 normal = -cameraNormal;
|
||||
#include apply_light_color
|
||||
|
||||
#include apply_interior_color
|
||||
#include apply_marker_color
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.354, IHM 1.17, MA 1.3.3.
|
||||
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.355, IHM 1.17, MA 1.3.4.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.354, IHM 1.17, MA 1.3.3.
|
||||
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.355, IHM 1.17, MA 1.3.4.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.354, IHM 1.17, MA 1.3.3.
|
||||
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.355, IHM 1.17, MA 1.3.4.
|
||||
*
|
||||
* @author molstar/ciftools package
|
||||
*/
|
||||
@@ -215,6 +215,28 @@ export const mmCIF_Schema = {
|
||||
* formal charge assignment normally found in chemical diagrams.
|
||||
*/
|
||||
pdbx_formal_charge: int,
|
||||
/**
|
||||
* This data item is an ordinal which identifies distinct chemical components in the atom_site category, both
|
||||
* polymeric and non-polymeric.
|
||||
*/
|
||||
pdbx_label_index: int,
|
||||
/**
|
||||
* The name of additional external databases with residue level mapping.
|
||||
*/
|
||||
pdbx_sifts_xref_db_name: str,
|
||||
/**
|
||||
* The accession code related to the additional external database entry.
|
||||
*/
|
||||
pdbx_sifts_xref_db_acc: str,
|
||||
/**
|
||||
* The sequence position of the external database entry that corresponds
|
||||
* to the residue mapping defined by the SIFTS process.
|
||||
*/
|
||||
pdbx_sifts_xref_db_num: str,
|
||||
/**
|
||||
* Describes the residue type of the given UniProt match
|
||||
*/
|
||||
pdbx_sifts_xref_db_res: str,
|
||||
/**
|
||||
* The model id corresponding to the atom site.
|
||||
* This data item is a pointer to _ihm_model_list.model_id
|
||||
@@ -682,7 +704,7 @@ export const mmCIF_Schema = {
|
||||
/**
|
||||
* An abbreviation that identifies the database.
|
||||
*/
|
||||
database_id: Aliased<'AFDB' | 'CAS' | 'CSD' | 'EMDB' | 'ICSD' | 'MA' | 'MDF' | 'MODBASE' | 'NDB' | 'NBS' | 'PDB' | 'PDF' | 'RCSB' | 'SMR' | 'EBI' | 'PDBE' | 'BMRB' | 'WWPDB' | 'PDB_ACC'>(str),
|
||||
database_id: Aliased<'AlphaFoldDB' | 'CAS' | 'CSD' | 'EMDB' | 'ICSD' | 'ModelArchive' | 'MDF' | 'MODBASE' | 'NDB' | 'NBS' | 'PDB' | 'PDF' | 'RCSB' | 'SWISS-MODEL_REPOSITORY' | 'EBI' | 'PDBE' | 'BMRB' | 'WWPDB' | 'PDB_ACC'>(str),
|
||||
/**
|
||||
* The code assigned by the database identified in
|
||||
* _database_2.database_id.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import { Model } from '../../../mol-model/structure';
|
||||
@@ -44,7 +45,7 @@ interface FormatPropertyProvider<T> {
|
||||
}
|
||||
|
||||
namespace FormatPropertyProvider {
|
||||
export function create<T>(descriptor: CustomPropertyDescriptor): FormatPropertyProvider<T> {
|
||||
export function create<T>(descriptor: CustomPropertyDescriptor, options?: { asDynamic?: boolean }): FormatPropertyProvider<T> {
|
||||
const { name } = descriptor;
|
||||
const formatRegistry = new FormatRegistry<T>();
|
||||
|
||||
@@ -55,21 +56,31 @@ namespace FormatPropertyProvider {
|
||||
return formatRegistry.isApplicable(model);
|
||||
},
|
||||
get(model: Model): T | undefined {
|
||||
if (model._staticPropertyData[name]) return model._staticPropertyData[name];
|
||||
const store = options?.asDynamic ? model._dynamicPropertyData : model._staticPropertyData;
|
||||
|
||||
if (store[name]) return store[name];
|
||||
if (model.customProperties.has(descriptor)) return;
|
||||
|
||||
const obtain = formatRegistry.get(model.sourceData.kind);
|
||||
if (!obtain) return;
|
||||
|
||||
model._staticPropertyData[name] = obtain(model);
|
||||
store[name] = obtain(model);
|
||||
model.customProperties.add(descriptor);
|
||||
return model._staticPropertyData[name];
|
||||
return store[name];
|
||||
},
|
||||
set(model: Model, value: T) {
|
||||
model._staticPropertyData[name] = value;
|
||||
if (options?.asDynamic) {
|
||||
model._dynamicPropertyData[name] = value;
|
||||
} else {
|
||||
model._staticPropertyData[name] = value;
|
||||
}
|
||||
},
|
||||
delete(model: Model) {
|
||||
delete model._staticPropertyData[name];
|
||||
if (options?.asDynamic) {
|
||||
delete model._dynamicPropertyData[name];
|
||||
} else {
|
||||
delete model._staticPropertyData[name];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2019-2022 Mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import { CustomPropertyDescriptor } from '../../../../mol-model/custom-property';
|
||||
@@ -42,7 +43,7 @@ export namespace IndexPairBonds {
|
||||
name: 'index_pair_bonds',
|
||||
};
|
||||
|
||||
export const Provider = FormatPropertyProvider.create<IndexPairBonds>(Descriptor);
|
||||
export const Provider = FormatPropertyProvider.create<IndexPairBonds>(Descriptor, { asDynamic: true });
|
||||
|
||||
export type Data = {
|
||||
pairs: {
|
||||
|
||||
@@ -11,30 +11,43 @@ import { Model } from '../../mol-model/structure';
|
||||
import { StructureElement } from '../../mol-model/structure/structure';
|
||||
import { CustomModelProperty } from '../common/custom-model-property';
|
||||
|
||||
export { BestDatabaseSequenceMapping };
|
||||
export { SIFTSMapping as SIFTSMapping };
|
||||
|
||||
interface BestDatabaseSequenceMapping {
|
||||
interface SIFTSMappingMapping {
|
||||
readonly dbName: string[],
|
||||
readonly accession: string[],
|
||||
readonly num: number[],
|
||||
readonly num: string[],
|
||||
readonly residue: string[]
|
||||
}
|
||||
|
||||
namespace BestDatabaseSequenceMapping {
|
||||
export const Provider: CustomModelProperty.Provider<{}, BestDatabaseSequenceMapping> = CustomModelProperty.createProvider({
|
||||
label: 'Best Database Sequence Mapping',
|
||||
namespace SIFTSMapping {
|
||||
export const Provider: CustomModelProperty.Provider<{}, SIFTSMappingMapping> = CustomModelProperty.createProvider({
|
||||
label: 'SIFTS Mapping',
|
||||
descriptor: CustomPropertyDescriptor({
|
||||
name: 'molstar_best_database_sequence_mapping'
|
||||
name: 'sifts_sequence_mapping'
|
||||
}),
|
||||
type: 'static',
|
||||
defaultParams: {},
|
||||
getParams: () => ({}),
|
||||
isApplicable: (data: Model) => MmcifFormat.is(data.sourceData) && data.sourceData.data.frame.categories?.atom_site?.fieldNames.indexOf('pdbx_sifts_xref_db_name') >= 0,
|
||||
isApplicable: (data: Model) => isAvailable(data),
|
||||
obtain: async (ctx, data) => {
|
||||
return { value: fromCif(data) };
|
||||
}
|
||||
});
|
||||
|
||||
export function isAvailable(model: Model) {
|
||||
if (!MmcifFormat.is(model.sourceData)) return false;
|
||||
|
||||
const {
|
||||
pdbx_sifts_xref_db_name: db_name,
|
||||
pdbx_sifts_xref_db_acc: db_acc,
|
||||
pdbx_sifts_xref_db_num: db_num,
|
||||
pdbx_sifts_xref_db_res: db_res
|
||||
} = model.sourceData.data.db.atom_site;
|
||||
|
||||
return db_name.isDefined && db_acc.isDefined && db_num.isDefined && db_res.isDefined;
|
||||
}
|
||||
|
||||
export function getKey(loc: StructureElement.Location) {
|
||||
const model = loc.unit.model;
|
||||
const data = Provider.get(model).value;
|
||||
@@ -55,22 +68,23 @@ namespace BestDatabaseSequenceMapping {
|
||||
return `${dbName} ${data.accession[rI]} ${data.num[rI]} ${data.residue[rI]}`;
|
||||
}
|
||||
|
||||
function fromCif(model: Model): BestDatabaseSequenceMapping | undefined {
|
||||
function fromCif(model: Model): SIFTSMappingMapping | undefined {
|
||||
if (!MmcifFormat.is(model.sourceData)) return;
|
||||
|
||||
const { atom_site } = model.sourceData.data.frame.categories;
|
||||
const db_name = atom_site.getField('pdbx_sifts_xref_db_name');
|
||||
const db_acc = atom_site.getField('pdbx_sifts_xref_db_acc');
|
||||
const db_num = atom_site.getField('pdbx_sifts_xref_db_num');
|
||||
const db_res = atom_site.getField('pdbx_sifts_xref_db_res');
|
||||
const {
|
||||
pdbx_sifts_xref_db_name: db_name,
|
||||
pdbx_sifts_xref_db_acc: db_acc,
|
||||
pdbx_sifts_xref_db_num: db_num,
|
||||
pdbx_sifts_xref_db_res: db_res
|
||||
} = model.sourceData.data.db.atom_site;
|
||||
|
||||
if (!db_name || !db_acc || !db_num || !db_res) return;
|
||||
if (!db_name.isDefined || !db_acc.isDefined || !db_num.isDefined || !db_res.isDefined) return;
|
||||
|
||||
const { atomSourceIndex } = model.atomicHierarchy;
|
||||
const { count, offsets: residueOffsets } = model.atomicHierarchy.residueAtomSegments;
|
||||
const dbName = new Array<string>(count);
|
||||
const accession = new Array<string>(count);
|
||||
const num = new Array<number>(count);
|
||||
const num = new Array<string>(count);
|
||||
const residue = new Array<string>(count);
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
@@ -79,15 +93,15 @@ namespace BestDatabaseSequenceMapping {
|
||||
if (db_name.valueKind(row) !== Column.ValueKind.Present) {
|
||||
dbName[i] = '';
|
||||
accession[i] = '';
|
||||
num[i] = 0;
|
||||
num[i] = '';
|
||||
residue[i] = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
dbName[i] = db_name.str(row);
|
||||
accession[i] = db_acc.str(row);
|
||||
num[i] = db_num.int(row);
|
||||
residue[i] = db_res.str(row);
|
||||
dbName[i] = db_name.value(row);
|
||||
accession[i] = db_acc.value(row);
|
||||
num[i] = db_num.value(row);
|
||||
residue[i] = db_res.value(row);
|
||||
}
|
||||
|
||||
return { dbName, accession, num, residue };
|
||||
@@ -12,27 +12,27 @@ import { Color } from '../../../mol-util/color';
|
||||
import { getPalette, getPaletteParams } from '../../../mol-util/color/palette';
|
||||
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
|
||||
import { CustomProperty } from '../../common/custom-property';
|
||||
import { BestDatabaseSequenceMapping } from '../best-database-mapping';
|
||||
import { SIFTSMapping } from '../sifts-mapping';
|
||||
|
||||
const DefaultColor = Color(0xFAFAFA);
|
||||
const Description = 'Assigns a color based on best dababase sequence mapping.';
|
||||
const Description = 'Assigns a color based on SIFTS mapping.';
|
||||
|
||||
// same colors for same accessions
|
||||
const globalAccessionMap = new Map<string, number>();
|
||||
|
||||
export const BestDatabaseSequenceMappingColorThemeParams = {
|
||||
export const SIFTSMappingColorThemeParams = {
|
||||
...getPaletteParams({ type: 'colors', colorList: 'set-1' }),
|
||||
};
|
||||
export type BestDatabaseSequenceMappingColorThemeParams = typeof BestDatabaseSequenceMappingColorThemeParams
|
||||
export function getBestDatabaseSequenceMappingColorThemeParams(ctx: ThemeDataContext) {
|
||||
return BestDatabaseSequenceMappingColorThemeParams; // TODO return copy
|
||||
export type SIFTSMappingColorThemeParams = typeof SIFTSMappingColorThemeParams
|
||||
export function getSIFTSMappingColorThemeParams(ctx: ThemeDataContext) {
|
||||
return SIFTSMappingColorThemeParams; // TODO return copy
|
||||
}
|
||||
export function BestDatabaseSequenceMappingColorTheme(ctx: ThemeDataContext, props: PD.Values<BestDatabaseSequenceMappingColorThemeParams>): ColorTheme<BestDatabaseSequenceMappingColorThemeParams> {
|
||||
export function SIFTSMappingColorTheme(ctx: ThemeDataContext, props: PD.Values<SIFTSMappingColorThemeParams>): ColorTheme<SIFTSMappingColorThemeParams> {
|
||||
let color: LocationColor;
|
||||
|
||||
if (ctx.structure) {
|
||||
for (const m of ctx.structure.models) {
|
||||
const mapping = BestDatabaseSequenceMapping.Provider.get(m).value;
|
||||
const mapping = SIFTSMapping.Provider.get(m).value;
|
||||
if (!mapping) continue;
|
||||
for (const acc of mapping.accession) {
|
||||
if (!acc || globalAccessionMap.has(acc)) continue;
|
||||
@@ -45,7 +45,7 @@ export function BestDatabaseSequenceMappingColorTheme(ctx: ThemeDataContext, pro
|
||||
const colorMap = new Map<string, Color>();
|
||||
|
||||
const getColor = (location: StructureElement.Location) => {
|
||||
const key = BestDatabaseSequenceMapping.getKey(location);
|
||||
const key = SIFTSMapping.getKey(location);
|
||||
if (!key) return DefaultColor;
|
||||
|
||||
if (colorMap.has(key)) return colorMap.get(key)!;
|
||||
@@ -70,7 +70,7 @@ export function BestDatabaseSequenceMappingColorTheme(ctx: ThemeDataContext, pro
|
||||
}
|
||||
|
||||
return {
|
||||
factory: BestDatabaseSequenceMappingColorTheme,
|
||||
factory: SIFTSMappingColorTheme,
|
||||
granularity: 'group',
|
||||
preferSmoothing: true,
|
||||
color,
|
||||
@@ -79,26 +79,26 @@ export function BestDatabaseSequenceMappingColorTheme(ctx: ThemeDataContext, pro
|
||||
};
|
||||
}
|
||||
|
||||
export const BestDatabaseSequenceMappingColorThemeProvider: ColorTheme.Provider<BestDatabaseSequenceMappingColorThemeParams, 'best-sequence-database-mapping'> = {
|
||||
name: 'best-sequence-database-mapping',
|
||||
label: 'Best Database Sequence Mapping',
|
||||
export const SIFTSMappingColorThemeProvider: ColorTheme.Provider<SIFTSMappingColorThemeParams, 'sifts-mapping'> = {
|
||||
name: 'sifts-mapping',
|
||||
label: 'SIFTS Mapping',
|
||||
category: ColorTheme.Category.Residue,
|
||||
factory: BestDatabaseSequenceMappingColorTheme,
|
||||
getParams: getBestDatabaseSequenceMappingColorThemeParams,
|
||||
defaultValues: PD.getDefaultValues(BestDatabaseSequenceMappingColorThemeParams),
|
||||
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure?.models.some(m => BestDatabaseSequenceMapping.Provider.isApplicable(m)),
|
||||
factory: SIFTSMappingColorTheme,
|
||||
getParams: getSIFTSMappingColorThemeParams,
|
||||
defaultValues: PD.getDefaultValues(SIFTSMappingColorThemeParams),
|
||||
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure?.models.some(m => SIFTSMapping.Provider.isApplicable(m)),
|
||||
ensureCustomProperties: {
|
||||
attach: async (ctx: CustomProperty.Context, data: ThemeDataContext) => {
|
||||
if (!data.structure) return;
|
||||
|
||||
for (const m of data.structure.models) {
|
||||
await BestDatabaseSequenceMapping.Provider.attach(ctx, m, void 0, true);
|
||||
await SIFTSMapping.Provider.attach(ctx, m, void 0, true);
|
||||
}
|
||||
},
|
||||
detach: (data) => {
|
||||
if (!data.structure) return;
|
||||
for (const m of data.structure.models) {
|
||||
BestDatabaseSequenceMapping.Provider.ref(m, false);
|
||||
SIFTSMapping.Provider.ref(m, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,11 @@
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { Column } from '../../../../mol-data/db';
|
||||
import { mmCIF_Database } from '../../../../mol-io/reader/cif/schema/mmcif';
|
||||
import { CifWriter } from '../../../../mol-io/writer/cif';
|
||||
import { MmcifFormat } from '../../../../mol-model-formats/structure/mmcif';
|
||||
import { SIFTSMapping } from '../../../../mol-model-props/sequence/sifts-mapping';
|
||||
import { StructureElement, Structure, StructureProperties as P } from '../../structure';
|
||||
import { CifExportContext } from '../mmcif';
|
||||
import CifField = CifWriter.Field
|
||||
@@ -26,7 +30,64 @@ function atom_site_auth_asym_id(e: StructureElement.Location) {
|
||||
return l + suffix;
|
||||
}
|
||||
|
||||
const atom_site_fields = () => CifWriter.fields<StructureElement.Location, Structure>()
|
||||
|
||||
const atom_site_pdbx_label_index = {
|
||||
shouldInclude(s: AtomSiteData) {
|
||||
return !!s.atom_site?.pdbx_label_index.isDefined;
|
||||
},
|
||||
value(e: StructureElement.Location, d: AtomSiteData) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_label_index.value(srcIndex);
|
||||
},
|
||||
};
|
||||
|
||||
const SIFTS = {
|
||||
shouldInclude(s: AtomSiteData) {
|
||||
return SIFTSMapping.isAvailable(s.structure.models[0]);
|
||||
},
|
||||
pdbx_sifts_xref_db_name: {
|
||||
value(e: StructureElement.Location, d: AtomSiteData) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_name.value(srcIndex);
|
||||
},
|
||||
valueKind(e: StructureElement.Location, d: any) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_name.valueKind(srcIndex);
|
||||
},
|
||||
},
|
||||
pdbx_sifts_xref_db_acc: {
|
||||
value(e: StructureElement.Location, d: AtomSiteData) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_acc.value(srcIndex);
|
||||
},
|
||||
valueKind(e: StructureElement.Location, d: any) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_acc.valueKind(srcIndex);
|
||||
},
|
||||
},
|
||||
pdbx_sifts_xref_db_num: {
|
||||
value(e: StructureElement.Location, d: AtomSiteData) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_num.value(srcIndex);
|
||||
},
|
||||
valueKind(e: StructureElement.Location, d: any) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_num.valueKind(srcIndex);
|
||||
},
|
||||
},
|
||||
pdbx_sifts_xref_db_res: {
|
||||
value(e: StructureElement.Location, d: AtomSiteData) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_res.value(srcIndex);
|
||||
},
|
||||
valueKind(e: StructureElement.Location, d: any) {
|
||||
const srcIndex = d.sourceIndex.value(e.element);
|
||||
return d.atom_site!.pdbx_sifts_xref_db_res.valueKind(srcIndex);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const atom_site_fields = () => CifWriter.fields<StructureElement.Location, AtomSiteData>()
|
||||
.str('group_PDB', P.residue.group_PDB)
|
||||
.index('id')
|
||||
.str('type_symbol', P.atom.type_symbol as any)
|
||||
@@ -62,18 +123,37 @@ const atom_site_fields = () => CifWriter.fields<StructureElement.Location, Struc
|
||||
.str('auth_asym_id', atom_site_auth_asym_id)
|
||||
|
||||
.int('pdbx_PDB_model_num', P.unit.model_num, { encoder: E.deltaRLE })
|
||||
|
||||
.int('pdbx_label_index', atom_site_pdbx_label_index.value, { shouldInclude: atom_site_pdbx_label_index.shouldInclude })
|
||||
|
||||
// SIFTS
|
||||
.str('pdbx_sifts_xref_db_name', SIFTS.pdbx_sifts_xref_db_name.value, { shouldInclude: SIFTS.shouldInclude, valueKind: SIFTS.pdbx_sifts_xref_db_name.valueKind })
|
||||
.str('pdbx_sifts_xref_db_acc', SIFTS.pdbx_sifts_xref_db_acc.value, { shouldInclude: SIFTS.shouldInclude, valueKind: SIFTS.pdbx_sifts_xref_db_acc.valueKind })
|
||||
.str('pdbx_sifts_xref_db_num', SIFTS.pdbx_sifts_xref_db_num.value, { shouldInclude: SIFTS.shouldInclude, valueKind: SIFTS.pdbx_sifts_xref_db_num.valueKind })
|
||||
.str('pdbx_sifts_xref_db_res', SIFTS.pdbx_sifts_xref_db_res.value, { shouldInclude: SIFTS.shouldInclude, valueKind: SIFTS.pdbx_sifts_xref_db_res.valueKind })
|
||||
|
||||
// .str('operator_name', P.unit.operator_name, {
|
||||
// shouldInclude: structure => structure.units.some(u => !u.conformation.operator.isIdentity)
|
||||
// })
|
||||
.getFields();
|
||||
|
||||
interface AtomSiteData {
|
||||
structure: Structure,
|
||||
sourceIndex: Column<number>,
|
||||
atom_site?: mmCIF_Database['atom_site']
|
||||
}
|
||||
|
||||
export const _atom_site: CifCategory<CifExportContext> = {
|
||||
name: 'atom_site',
|
||||
instance({ structures }: CifExportContext) {
|
||||
return {
|
||||
fields: atom_site_fields(),
|
||||
source: structures.map(s => ({
|
||||
data: s,
|
||||
data: {
|
||||
structure: s,
|
||||
sourceIndex: s.model.atomicHierarchy.atomSourceIndex,
|
||||
atom_site: MmcifFormat.is(s.model.sourceData) ? s.model.sourceData.data.db.atom_site : void 0
|
||||
} as AtomSiteData,
|
||||
rowCount: s.elementCount,
|
||||
keys: () => s.elementLocations()
|
||||
}))
|
||||
|
||||
@@ -78,12 +78,12 @@ function findElements<T extends SecondaryStructure.Element>(ctx: CifExportContex
|
||||
const ssElements: SSElement<any>[] = [];
|
||||
|
||||
const structure = ctx.structures[0];
|
||||
for (const unit of structure.units) {
|
||||
// currently can only support this for "identity" operators.
|
||||
if (!Unit.isAtomic(unit) || !unit.conformation.operator.isIdentity) continue;
|
||||
for (const { units } of structure.unitSymmetryGroups) {
|
||||
const u = units[0];
|
||||
if (!Unit.isAtomic(u)) continue;
|
||||
|
||||
const segs = unit.model.atomicHierarchy.residueAtomSegments;
|
||||
const residues = Segmentation.transientSegments(segs, unit.elements);
|
||||
const segs = u.model.atomicHierarchy.residueAtomSegments;
|
||||
const residues = Segmentation.transientSegments(segs, u.elements);
|
||||
|
||||
let current: Segmentation.Segment, move = true;
|
||||
while (residues.hasNext) {
|
||||
@@ -104,8 +104,8 @@ function findElements<T extends SecondaryStructure.Element>(ctx: CifExportContex
|
||||
if (startIdx !== key[current.index]) {
|
||||
move = false;
|
||||
ssElements[ssElements.length] = {
|
||||
start: StructureElement.Location.create(structure, unit, segs.offsets[start]),
|
||||
end: StructureElement.Location.create(structure, unit, segs.offsets[prev]),
|
||||
start: StructureElement.Location.create(structure, u, segs.offsets[start]),
|
||||
end: StructureElement.Location.create(structure, u, segs.offsets[prev]),
|
||||
length: prev - start + 1,
|
||||
element
|
||||
};
|
||||
|
||||
@@ -1,28 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
* @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
|
||||
*/
|
||||
|
||||
import { Segmentation } from '../../../../mol-data/int';
|
||||
import { Mat4 } from '../../../../mol-math/linear-algebra';
|
||||
import { MinimizeRmsd } from '../../../../mol-math/linear-algebra/3d/minimize-rmsd';
|
||||
import { BestDatabaseSequenceMapping } from '../../../../mol-model-props/sequence/best-database-mapping';
|
||||
import { SIFTSMapping } from '../../../../mol-model-props/sequence/sifts-mapping';
|
||||
import { ElementIndex } from '../../model/indexing';
|
||||
import { Structure } from '../structure';
|
||||
import { Unit } from '../unit';
|
||||
|
||||
export interface AlignmentResult {
|
||||
export interface AlignmentResultEntry {
|
||||
transform: MinimizeRmsd.Result,
|
||||
pivot: number,
|
||||
other: number
|
||||
}
|
||||
|
||||
export function alignAndSuperposeWithBestDatabaseMapping(structures: Structure[]): AlignmentResult[] {
|
||||
export interface AlignmentResult {
|
||||
entries: AlignmentResultEntry[],
|
||||
zeroOverlapPairs: [number, number][],
|
||||
failedPairs: [number, number][]
|
||||
}
|
||||
|
||||
export function alignAndSuperposeWithSIFTSMapping(structures: Structure[], options?: { traceOnly?: boolean }): AlignmentResult {
|
||||
const indexMap = new Map<string, IndexEntry>();
|
||||
|
||||
for (let i = 0; i < structures.length; i++) {
|
||||
buildIndex(structures[i], indexMap, i);
|
||||
buildIndex(structures[i], indexMap, i, options?.traceOnly ?? true);
|
||||
}
|
||||
|
||||
const index = Array.from(indexMap.values());
|
||||
@@ -30,15 +36,26 @@ export function alignAndSuperposeWithBestDatabaseMapping(structures: Structure[]
|
||||
// TODO: support non-first structure pivots
|
||||
const pairs = findPairs(structures.length, index);
|
||||
|
||||
const ret: AlignmentResult[] = [];
|
||||
const zeroOverlapPairs: AlignmentResult['zeroOverlapPairs'] = [];
|
||||
const failedPairs: AlignmentResult['failedPairs'] = [];
|
||||
|
||||
|
||||
const entries: AlignmentResultEntry[] = [];
|
||||
for (const p of pairs) {
|
||||
const [a, b] = getPositionTables(index, p.i, p.j, p.count);
|
||||
const transform = MinimizeRmsd.compute({ a, b });
|
||||
console.log(Mat4.makeTable(transform.bTransform), transform.rmsd);
|
||||
ret.push({ transform, pivot: p.i, other: p.j });
|
||||
if (p.count === 0) {
|
||||
zeroOverlapPairs.push([p.i, p.j]);
|
||||
} else {
|
||||
const [a, b] = getPositionTables(index, p.i, p.j, p.count);
|
||||
const transform = MinimizeRmsd.compute({ a, b });
|
||||
if (Number.isNaN(transform.rmsd)) {
|
||||
failedPairs.push([p.i, p.j]);
|
||||
} else {
|
||||
entries.push({ transform, pivot: p.i, other: p.j });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return { entries, zeroOverlapPairs, failedPairs };
|
||||
}
|
||||
|
||||
function getPositionTables(index: IndexEntry[], pivot: number, other: number, N: number) {
|
||||
@@ -53,7 +70,6 @@ function getPositionTables(index: IndexEntry[], pivot: number, other: number, N:
|
||||
|
||||
const l = Math.min(a[2] - a[1], b[2] - b[1]);
|
||||
|
||||
// TODO: allow to use just backbone atoms?
|
||||
// TODO: check if residue types match?
|
||||
for (let i = 0; i < l; i++) {
|
||||
let eI = (a[1] + i) as ElementIndex;
|
||||
@@ -121,19 +137,20 @@ interface IndexEntry {
|
||||
pivots: { [i: number]: [unit: Unit.Atomic, start: ElementIndex, end: ElementIndex] | undefined }
|
||||
}
|
||||
|
||||
function buildIndex(structure: Structure, index: Map<string, IndexEntry>, sI: number) {
|
||||
function buildIndex(structure: Structure, index: Map<string, IndexEntry>, sI: number, traceOnly: boolean) {
|
||||
for (const unit of structure.units) {
|
||||
if (unit.kind !== Unit.Kind.Atomic) continue;
|
||||
|
||||
const { elements, model } = unit;
|
||||
|
||||
const map = BestDatabaseSequenceMapping.Provider.get(model).value;
|
||||
const map = SIFTSMapping.Provider.get(model).value;
|
||||
if (!map) return;
|
||||
|
||||
const { dbName, accession, num } = map;
|
||||
|
||||
const chainsIt = Segmentation.transientSegments(unit.model.atomicHierarchy.chainAtomSegments, elements);
|
||||
const residuesIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements);
|
||||
const traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex;
|
||||
|
||||
while (chainsIt.hasNext) {
|
||||
const chainSegment = chainsIt.move();
|
||||
@@ -144,8 +161,15 @@ function buildIndex(structure: Structure, index: Map<string, IndexEntry>, sI: nu
|
||||
|
||||
if (!dbName[rI]) continue;
|
||||
|
||||
const start = elements[residueSegment.start];
|
||||
const end = elements[residueSegment.end - 1] + 1 as ElementIndex;
|
||||
let start, end;
|
||||
if (traceOnly) {
|
||||
start = traceElementIndex[rI];
|
||||
if (start === -1) continue;
|
||||
end = start + 1 as ElementIndex;
|
||||
} else {
|
||||
start = elements[residueSegment.start];
|
||||
end = elements[residueSegment.end - 1] + 1 as ElementIndex;
|
||||
}
|
||||
|
||||
const key = `${dbName[rI]}-${accession[rI]}-${num[rI]}`;
|
||||
|
||||
@@ -161,6 +185,4 @@ function buildIndex(structure: Structure, index: Map<string, IndexEntry>, sI: nu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(index);
|
||||
}
|
||||
@@ -24,8 +24,6 @@ import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bo
|
||||
import { StructConn } from '../../../mol-model-formats/structure/property/bonds/struct_conn';
|
||||
import { StructureRepresentationRegistry } from '../../../mol-repr/structure/registry';
|
||||
import { assertUnreachable } from '../../../mol-util/type-helpers';
|
||||
import { Color } from '../../../mol-util/color';
|
||||
import { PostprocessingParams } from '../../../mol-canvas3d/passes/postprocessing';
|
||||
|
||||
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; }
|
||||
@@ -39,6 +37,7 @@ export namespace StructureRepresentationPresetProvider {
|
||||
|
||||
export const CommonParams = {
|
||||
ignoreHydrogens: PD.Optional(PD.Boolean(false)),
|
||||
ignoreLight: PD.Optional(PD.Boolean(false)),
|
||||
quality: PD.Optional(PD.Select<VisualQuality>('auto', VisualQualityOptions)),
|
||||
theme: PD.Optional(PD.Group({
|
||||
globalName: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')),
|
||||
@@ -70,9 +69,11 @@ export namespace StructureRepresentationPresetProvider {
|
||||
const typeParams = {
|
||||
quality: plugin.managers.structure.component.state.options.visualQuality,
|
||||
ignoreHydrogens: !plugin.managers.structure.component.state.options.showHydrogens,
|
||||
ignoreLight: plugin.managers.structure.component.state.options.ignoreLight,
|
||||
};
|
||||
if (params.quality && params.quality !== 'auto') typeParams.quality = params.quality;
|
||||
if (params.ignoreHydrogens !== void 0) typeParams.ignoreHydrogens = !!params.ignoreHydrogens;
|
||||
if (params.ignoreLight !== void 0) typeParams.ignoreLight = !!params.ignoreLight;
|
||||
const color: ColorTheme.BuiltIn | undefined = params.theme?.globalName ? params.theme?.globalName : void 0;
|
||||
const ballAndStickColor: ColorTheme.BuiltInParams<'element-symbol'> = params.theme?.carbonColor !== undefined
|
||||
? { carbonColor: getCarbonColorParams(params.theme?.carbonColor) }
|
||||
@@ -100,15 +101,6 @@ type CommonParams = StructureRepresentationPresetProvider.CommonParams
|
||||
const reprBuilder = StructureRepresentationPresetProvider.reprBuilder;
|
||||
const updateFocusRepr = StructureRepresentationPresetProvider.updateFocusRepr;
|
||||
|
||||
function resetPostprocessingProps(plugin: PluginContext) {
|
||||
if (plugin.canvas3d) {
|
||||
const p = PD.getDefaultValues(PostprocessingParams);
|
||||
plugin.canvas3d.setProps({
|
||||
postprocessing: { outline: p.outline, occlusion: p.occlusion }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const auto = StructureRepresentationPresetProvider({
|
||||
id: 'preset-structure-representation-auto',
|
||||
display: {
|
||||
@@ -148,7 +140,6 @@ const empty = StructureRepresentationPresetProvider({
|
||||
id: 'preset-structure-representation-empty',
|
||||
display: { name: 'Empty', description: 'Removes all existing representations.' },
|
||||
async apply(ref, params, plugin) {
|
||||
resetPostprocessingProps(plugin);
|
||||
return { };
|
||||
}
|
||||
});
|
||||
@@ -203,8 +194,6 @@ const polymerAndLigand = StructureRepresentationPresetProvider({
|
||||
await update.commit({ revertOnError: false });
|
||||
await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
|
||||
|
||||
resetPostprocessingProps(plugin);
|
||||
|
||||
return { components, representations };
|
||||
}
|
||||
});
|
||||
@@ -244,8 +233,6 @@ const proteinAndNucleic = StructureRepresentationPresetProvider({
|
||||
await update.commit({ revertOnError: true });
|
||||
await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
|
||||
|
||||
resetPostprocessingProps(plugin);
|
||||
|
||||
return { components, representations };
|
||||
}
|
||||
});
|
||||
@@ -298,8 +285,6 @@ const coarseSurface = StructureRepresentationPresetProvider({
|
||||
await update.commit({ revertOnError: true });
|
||||
await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
|
||||
|
||||
resetPostprocessingProps(plugin);
|
||||
|
||||
return { components, representations };
|
||||
}
|
||||
});
|
||||
@@ -333,8 +318,6 @@ const polymerCartoon = StructureRepresentationPresetProvider({
|
||||
await update.commit({ revertOnError: true });
|
||||
await updateFocusRepr(plugin, structure, params.theme?.focus?.name, params.theme?.focus?.params);
|
||||
|
||||
resetPostprocessingProps(plugin);
|
||||
|
||||
return { components, representations };
|
||||
}
|
||||
});
|
||||
@@ -401,8 +384,6 @@ const atomicDetail = StructureRepresentationPresetProvider({
|
||||
await update.commit({ revertOnError: true });
|
||||
await updateFocusRepr(plugin, structure, params.theme?.focus?.name ?? color, params.theme?.focus?.params ?? colorParams);
|
||||
|
||||
resetPostprocessingProps(plugin);
|
||||
|
||||
return { components, representations };
|
||||
}
|
||||
});
|
||||
@@ -436,21 +417,6 @@ const illustrative = StructureRepresentationPresetProvider({
|
||||
await update.commit({ revertOnError: true });
|
||||
await updateFocusRepr(plugin, structure, params.theme?.focus?.name ?? color, params.theme?.focus?.params);
|
||||
|
||||
if (plugin.canvas3d) {
|
||||
plugin.canvas3d.setProps({
|
||||
postprocessing: {
|
||||
outline: {
|
||||
name: 'on',
|
||||
params: { scale: 1, color: Color(0x000000), threshold: 0.25 }
|
||||
},
|
||||
occlusion: {
|
||||
name: 'on',
|
||||
params: { bias: 0.9, blurKernelSize: 15, radius: 5, samples: 32 }
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return { components, representations };
|
||||
}
|
||||
});
|
||||
@@ -471,6 +437,6 @@ export const PresetStructureRepresentations = {
|
||||
'polymer-and-ligand': polymerAndLigand,
|
||||
'protein-and-nucleic': proteinAndNucleic,
|
||||
'coarse-surface': coarseSurface,
|
||||
'illustrative': illustrative,
|
||||
illustrative,
|
||||
};
|
||||
export type PresetStructureRepresentations = typeof PresetStructureRepresentations;
|
||||
@@ -29,7 +29,7 @@ export class StructureRepresentationBuilder {
|
||||
|
||||
readonly defaultProvider = PresetStructureRepresentations.auto;
|
||||
|
||||
private resolveProvider(ref: StructureRepresentationPresetProviderRef) {
|
||||
resolveProvider(ref: StructureRepresentationPresetProviderRef) {
|
||||
return typeof ref === 'string'
|
||||
? PresetStructureRepresentations[ref as keyof PresetStructureRepresentations] ?? arrayFind(this._providers, p => p.id === ref)
|
||||
: ref;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 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>
|
||||
@@ -71,6 +71,7 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
await update.commit();
|
||||
await this.plugin.state.updateBehavior(StructureFocusRepresentation, p => {
|
||||
p.ignoreHydrogens = !options.showHydrogens;
|
||||
p.ignoreLight = options.ignoreLight;
|
||||
p.material = options.materialStyle;
|
||||
p.clip = options.clipObjects;
|
||||
});
|
||||
@@ -79,16 +80,17 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
}
|
||||
|
||||
private updateReprParams(update: StateBuilder.Root, component: StructureComponentRef) {
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const { showHydrogens, visualQuality: quality, ignoreLight, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const ignoreHydrogens = !showHydrogens;
|
||||
for (const r of component.representations) {
|
||||
if (r.cell.transform.transformer !== StructureRepresentation3D) continue;
|
||||
|
||||
const params = r.cell.transform.params as StateTransformer.Params<StructureRepresentation3D>;
|
||||
if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.quality !== quality || !shallowEqual(params.type.params.material, material) || !PD.areEqual(Clip.Params, params.type.params.clip, clip)) {
|
||||
if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.quality !== quality || params.type.params.ignoreLight !== ignoreLight || !shallowEqual(params.type.params.material, material) || !PD.areEqual(Clip.Params, params.type.params.clip, clip)) {
|
||||
update.to(r.cell).update(old => {
|
||||
old.type.params.ignoreHydrogens = ignoreHydrogens;
|
||||
old.type.params.quality = quality;
|
||||
old.type.params.ignoreLight = ignoreLight;
|
||||
old.type.params.material = material;
|
||||
old.type.params.clip = clip;
|
||||
});
|
||||
@@ -309,9 +311,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
addRepresentation(components: ReadonlyArray<StructureComponentRef>, type: string) {
|
||||
if (components.length === 0) return;
|
||||
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const { showHydrogens, visualQuality: quality, ignoreLight, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const ignoreHydrogens = !showHydrogens;
|
||||
const typeParams = { ignoreHydrogens, quality, material, clip };
|
||||
const typeParams = { ignoreHydrogens, quality, ignoreLight, material, clip };
|
||||
|
||||
return this.plugin.dataTransaction(async () => {
|
||||
for (const component of components) {
|
||||
@@ -346,9 +348,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
|
||||
const xs = structures || this.currentStructures;
|
||||
if (xs.length === 0) return;
|
||||
|
||||
const { showHydrogens, visualQuality: quality, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const { showHydrogens, visualQuality: quality, ignoreLight, materialStyle: material, clipObjects: clip } = this.state.options;
|
||||
const ignoreHydrogens = !showHydrogens;
|
||||
const typeParams = { ignoreHydrogens, quality, material, clip };
|
||||
const typeParams = { ignoreHydrogens, quality, ignoreLight, material, clip };
|
||||
|
||||
const componentKey = UUID.create22();
|
||||
for (const s of xs) {
|
||||
@@ -458,6 +460,7 @@ namespace StructureComponentManager {
|
||||
export const OptionsParams = {
|
||||
showHydrogens: PD.Boolean(true, { description: 'Toggle display of hydrogen atoms in representations' }),
|
||||
visualQuality: PD.Select('auto', VisualQualityOptions, { description: 'Control the visual/rendering quality of representations' }),
|
||||
ignoreLight: PD.Boolean(false, { description: 'Ignore light for stylized rendering of representtions' }),
|
||||
materialStyle: Material.getParam(),
|
||||
clipObjects: PD.Group(Clip.Params),
|
||||
interactions: PD.Group(InteractionsProvider.defaultParams, { label: 'Non-covalent Interactions' }),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 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>
|
||||
@@ -24,6 +24,7 @@ import { StructureSourceControls } from './structure/source';
|
||||
import { VolumeStreamingControls, VolumeSourceControls } from './structure/volume';
|
||||
import { PluginConfig } from '../mol-plugin/config';
|
||||
import { StructureSuperpositionControls } from './structure/superposition';
|
||||
import { StructureQuickStylesControls } from './structure/quick-styles';
|
||||
|
||||
export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: boolean, label: string }> {
|
||||
state = { show: false, label: '' };
|
||||
@@ -292,6 +293,7 @@ export class DefaultStructureTools extends PluginUIComponent {
|
||||
<StructureSourceControls />
|
||||
<StructureMeasurementsControls />
|
||||
<StructureSuperpositionControls />
|
||||
<StructureQuickStylesControls />
|
||||
<StructureComponentControls />
|
||||
{this.plugin.config.get(PluginConfig.VolumeStreaming.Enabled) && <VolumeStreamingControls />}
|
||||
<VolumeSourceControls />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 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>
|
||||
@@ -38,10 +38,10 @@ export function MoleculeSvg() { return _Molecule; }
|
||||
// The following icons are adapted from https://materialdesignicons.com/ and
|
||||
// licensed with https://github.com/Templarian/MaterialDesign/blob/master/LICENSE
|
||||
|
||||
const _CubeOutline = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z" /></svg>;
|
||||
const _CubeOutline = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d='M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z' /></svg>;
|
||||
export function CubeOutlineSvg() { return _CubeOutline; }
|
||||
|
||||
const _CubeScan = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d="M17,22V20H20V17H22V20.5C22,20.89 21.84,21.24 21.54,21.54C21.24,21.84 20.89,22 20.5,22H17M7,22H3.5C3.11,22 2.76,21.84 2.46,21.54C2.16,21.24 2,20.89 2,20.5V17H4V20H7V22M17,2H20.5C20.89,2 21.24,2.16 21.54,2.46C21.84,2.76 22,3.11 22,3.5V7H20V4H17V2M7,2V4H4V7H2V3.5C2,3.11 2.16,2.76 2.46,2.46C2.76,2.16 3.11,2 3.5,2H7M13,17.25L17,14.95V10.36L13,12.66V17.25M12,10.92L16,8.63L12,6.28L8,8.63L12,10.92M7,14.95L11,17.25V12.66L7,10.36V14.95M18.23,7.59C18.73,7.91 19,8.34 19,8.91V15.23C19,15.8 18.73,16.23 18.23,16.55L12.75,19.73C12.25,20.05 11.75,20.05 11.25,19.73L5.77,16.55C5.27,16.23 5,15.8 5,15.23V8.91C5,8.34 5.27,7.91 5.77,7.59L11.25,4.41C11.5,4.28 11.75,4.22 12,4.22C12.25,4.22 12.5,4.28 12.75,4.41L18.23,7.59Z" /></svg>;
|
||||
const _CubeScan = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d='M17,22V20H20V17H22V20.5C22,20.89 21.84,21.24 21.54,21.54C21.24,21.84 20.89,22 20.5,22H17M7,22H3.5C3.11,22 2.76,21.84 2.46,21.54C2.16,21.24 2,20.89 2,20.5V17H4V20H7V22M17,2H20.5C20.89,2 21.24,2.16 21.54,2.46C21.84,2.76 22,3.11 22,3.5V7H20V4H17V2M7,2V4H4V7H2V3.5C2,3.11 2.16,2.76 2.46,2.46C2.76,2.16 3.11,2 3.5,2H7M13,17.25L17,14.95V10.36L13,12.66V17.25M12,10.92L16,8.63L12,6.28L8,8.63L12,10.92M7,14.95L11,17.25V12.66L7,10.36V14.95M18.23,7.59C18.73,7.91 19,8.34 19,8.91V15.23C19,15.8 18.73,16.23 18.23,16.55L12.75,19.73C12.25,20.05 11.75,20.05 11.25,19.73L5.77,16.55C5.27,16.23 5,15.8 5,15.23V8.91C5,8.34 5.27,7.91 5.77,7.59L11.25,4.41C11.5,4.28 11.75,4.22 12,4.22C12.25,4.22 12.5,4.28 12.75,4.41L18.23,7.59Z' /></svg>;
|
||||
export function CubeScanSvg() { return _CubeScan; }
|
||||
|
||||
const _CubeSend = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d="M16,4L9,8.04V15.96L16,20L23,15.96V8.04M16,6.31L19.8,8.5L16,10.69L12.21,8.5M0,7V9H7V7M11,10.11L15,12.42V17.11L11,14.81M21,10.11V14.81L17,17.11V12.42M2,11V13H7V11M4,15V17H7V15" /></svg>;
|
||||
@@ -53,9 +53,12 @@ export function CursorDefaultOutlineSvg() { return _CursorDefaultOutline; }
|
||||
const _FileOutline = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path fill='currentColor' d='M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z' /></svg>;
|
||||
export function FileOutlineSvg() { return _FileOutline; }
|
||||
|
||||
const _PencilRuler = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d="M3 17.25V21H6.75L17.81 9.93L14.06 6.18L3 17.25M22.61 18.36L18.36 22.61L13.16 17.41L14.93 15.64L15.93 16.64L18.4 14.16L19.82 15.58L18.36 17L19.42 18L20.84 16.6L22.61 18.36M6.61 10.83L1.39 5.64L5.64 1.39L7.4 3.16L4.93 5.64L6 6.7L8.46 4.22L9.88 5.64L8.46 7.05L9.46 8.05L6.61 10.83M20.71 7C21.1 6.61 21.1 6 20.71 5.59L18.37 3.29C18 2.9 17.35 2.9 16.96 3.29L15.12 5.12L18.87 8.87L20.71 7Z" /></svg>;
|
||||
const _PencilRuler = <svg width='24px' height='24px' viewBox='0 0 24 24' strokeWidth='0.1px'><path d='M3 17.25V21H6.75L17.81 9.93L14.06 6.18L3 17.25M22.61 18.36L18.36 22.61L13.16 17.41L14.93 15.64L15.93 16.64L18.4 14.16L19.82 15.58L18.36 17L19.42 18L20.84 16.6L22.61 18.36M6.61 10.83L1.39 5.64L5.64 1.39L7.4 3.16L4.93 5.64L6 6.7L8.46 4.22L9.88 5.64L8.46 7.05L9.46 8.05L6.61 10.83M20.71 7C21.1 6.61 21.1 6 20.71 5.59L18.37 3.29C18 2.9 17.35 2.9 16.96 3.29L15.12 5.12L18.87 8.87L20.71 7Z' /></svg>;
|
||||
export function PencilRulerSvg() { return _PencilRuler; }
|
||||
|
||||
const _MagicWand = <svg width='24px' height='24px' viewBox='0 0 24 24'><path fill='currentColor' d='M7.5,5.6L5,7L6.4,4.5L5,2L7.5,3.4L10,2L8.6,4.5L10,7L7.5,5.6M19.5,15.4L22,14L20.6,16.5L22,19L19.5,17.6L17,19L18.4,16.5L17,14L19.5,15.4M22,2L20.6,4.5L22,7L19.5,5.6L17,7L18.4,4.5L17,2L19.5,3.4L22,2M13.34,12.78L15.78,10.34L13.66,8.22L11.22,10.66L13.34,12.78M14.37,7.29L16.71,9.63C17.1,10 17.1,10.65 16.71,11.04L5.04,22.71C4.65,23.1 4,23.1 3.63,22.71L1.29,20.37C0.9,20 0.9,19.35 1.29,18.96L12.96,7.29C13.35,6.9 14,6.9 14.37,7.29Z' /></svg>;
|
||||
export function MagicWandSvg() { return _MagicWand; }
|
||||
|
||||
// The following icons are adapted from https://material-ui.com/components/material-icons/ and
|
||||
// licensed with https://github.com/mui-org/material-ui/blob/master/LICENSE
|
||||
|
||||
|
||||
107
src/mol-plugin-ui/structure/quick-styles.tsx
Normal file
107
src/mol-plugin-ui/structure/quick-styles.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { PresetStructureRepresentations } from '../../mol-plugin-state/builder/structure/representation-preset';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import { CollapsableControls, PurePluginUIComponent } from '../base';
|
||||
import { Button } from '../controls/common';
|
||||
import { MagicWandSvg } from '../controls/icons';
|
||||
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
||||
import { PostprocessingParams } from '../../mol-canvas3d/passes/postprocessing';
|
||||
import { PluginConfig } from '../../mol-plugin/config';
|
||||
import { StructureComponentManager } from '../../mol-plugin-state/manager/structure/component';
|
||||
|
||||
export class StructureQuickStylesControls extends CollapsableControls {
|
||||
defaultState() {
|
||||
return {
|
||||
isCollapsed: false,
|
||||
header: 'Quick Styles',
|
||||
brand: { accent: 'gray' as const, svg: MagicWandSvg }
|
||||
};
|
||||
}
|
||||
|
||||
renderControls() {
|
||||
return <>
|
||||
<QuickStyles />
|
||||
</>;
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickStyles extends PurePluginUIComponent {
|
||||
async default() {
|
||||
const { structures } = this.plugin.managers.structure.hierarchy.selection;
|
||||
const preset = this.plugin.config.get(PluginConfig.Structure.DefaultRepresentationPreset) || PresetStructureRepresentations.auto.id;
|
||||
const provider = this.plugin.builders.structure.representation.resolveProvider(preset);
|
||||
await this.plugin.managers.structure.component.applyPreset(structures, provider);
|
||||
|
||||
this.plugin.managers.structure.component.setOptions(PD.getDefaultValues(StructureComponentManager.OptionsParams));
|
||||
|
||||
if (this.plugin.canvas3d) {
|
||||
const p = PD.getDefaultValues(PostprocessingParams);
|
||||
this.plugin.canvas3d.setProps({
|
||||
postprocessing: { outline: p.outline, occlusion: p.occlusion }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async illustrative() {
|
||||
const { structures } = this.plugin.managers.structure.hierarchy.selection;
|
||||
await this.plugin.managers.structure.component.applyPreset(structures, PresetStructureRepresentations.illustrative);
|
||||
|
||||
if (this.plugin.canvas3d) {
|
||||
this.plugin.canvas3d.setProps({
|
||||
postprocessing: {
|
||||
outline: {
|
||||
name: 'on',
|
||||
params: { scale: 1, color: Color(0x000000), threshold: 0.25 }
|
||||
},
|
||||
occlusion: {
|
||||
name: 'on',
|
||||
params: { bias: 0.9, blurKernelSize: 15, radius: 5, samples: 32 }
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async stylized() {
|
||||
this.plugin.managers.structure.component.setOptions({ ...this.plugin.managers.structure.component.state.options, ignoreLight: true });
|
||||
|
||||
if (this.plugin.canvas3d) {
|
||||
const pp = this.plugin.canvas3d.props.postprocessing;
|
||||
this.plugin.canvas3d.setProps({
|
||||
postprocessing: {
|
||||
outline: {
|
||||
name: 'on',
|
||||
params: pp.outline.name === 'on'
|
||||
? pp.outline.params
|
||||
: { scale: 1, color: Color(0x000000), threshold: 0.33 }
|
||||
},
|
||||
occlusion: {
|
||||
name: 'on',
|
||||
params: pp.occlusion.name === 'on'
|
||||
? pp.occlusion.params
|
||||
: { bias: 0.9, blurKernelSize: 15, radius: 5, samples: 32 }
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className='msp-flex-row'>
|
||||
<Button noOverflow title='Applies default representation preset. Set outline and occlusion effects to defaults.' onClick={() => this.default()} style={{ width: 'auto' }}>
|
||||
Default
|
||||
</Button>
|
||||
<Button noOverflow title='Applies no representation preset. Enables outline and occlusion effects. Enables ignore-light representation parameter.' onClick={() => this.stylized()} style={{ width: 'auto' }}>
|
||||
Stylized
|
||||
</Button>
|
||||
<Button noOverflow title='Applies illustrative representation preset. Enables outline and occlusion effects. Enables ignore-light parameter.' onClick={() => this.illustrative()} style={{ width: 'auto' }}>
|
||||
Illustrative
|
||||
</Button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
* @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
|
||||
*/
|
||||
|
||||
import { CollapsableControls, PurePluginUIComponent } from '../base';
|
||||
@@ -20,9 +21,9 @@ import { ParameterControls } from '../controls/parameters';
|
||||
import { stripTags } from '../../mol-util/string';
|
||||
import { StructureSelectionHistoryEntry } from '../../mol-plugin-state/manager/structure/selection';
|
||||
import { ToggleSelectionModeButton } from './selection';
|
||||
import { alignAndSuperposeWithBestDatabaseMapping } from '../../mol-model/structure/structure/util/superposition-db-mapping';
|
||||
import { alignAndSuperposeWithSIFTSMapping } from '../../mol-model/structure/structure/util/superposition-sifts-mapping';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
import { BestDatabaseSequenceMapping } from '../../mol-model-props/sequence/best-database-mapping';
|
||||
import { SIFTSMapping } from '../../mol-model-props/sequence/sifts-mapping';
|
||||
|
||||
export class StructureSuperpositionControls extends CollapsableControls {
|
||||
defaultState() {
|
||||
@@ -48,7 +49,8 @@ export class StructureSuperpositionControls extends CollapsableControls {
|
||||
}
|
||||
|
||||
export const StructureSuperpositionParams = {
|
||||
alignSequences: PD.Boolean(true, { isEssential: true, description: 'Perform a sequence alignment and use the aligned residue pairs to guide the 3D superposition.' }),
|
||||
alignSequences: PD.Boolean(true, { isEssential: true, description: 'For Chain-based 3D superposition, perform a sequence alignment and use the aligned residue pairs to guide the 3D superposition.' }),
|
||||
traceOnly: PD.Boolean(true, { description: 'For Chain- and Uniprot-based 3D superposition, base superposition only on CA (and equivalent) atoms.' })
|
||||
};
|
||||
const DefaultStructureSuperpositionOptions = PD.getDefaultValues(StructureSuperpositionParams);
|
||||
export type StructureSuperpositionOptions = PD.ValuesFor<typeof StructureSuperpositionParams>
|
||||
@@ -94,7 +96,7 @@ export class SuperpositionControls extends PurePluginUIComponent<{ }, Superposit
|
||||
});
|
||||
|
||||
this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, sel => {
|
||||
this.setState({ canUseDb: sel.structures.every(s => !!s.cell.obj?.data && s.cell.obj.data.models.some(m => BestDatabaseSequenceMapping.Provider.isApplicable(m))) });
|
||||
this.setState({ canUseDb: sel.structures.every(s => !!s.cell.obj?.data && s.cell.obj.data.models.some(m => SIFTSMapping.Provider.isApplicable(m))) });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -123,10 +125,10 @@ export class SuperpositionControls extends PurePluginUIComponent<{ }, Superposit
|
||||
}
|
||||
|
||||
superposeChains = async () => {
|
||||
const { query } = StructureSelectionQueries.trace;
|
||||
const { query } = this.state.options.traceOnly ? StructureSelectionQueries.trace : StructureSelectionQueries.polymer;
|
||||
const entries = this.chainEntries;
|
||||
|
||||
const traceLocis = entries.map((e, i) => {
|
||||
const locis = entries.map((e, i) => {
|
||||
const s = StructureElement.Loci.toStructure(e.loci);
|
||||
const loci = StructureSelection.toLociWithSourceUnits(query(new QueryContext(s)));
|
||||
return StructureElement.Loci.remap(loci, i === 0
|
||||
@@ -136,11 +138,11 @@ export class SuperpositionControls extends PurePluginUIComponent<{ }, Superposit
|
||||
});
|
||||
|
||||
const transforms = this.state.options.alignSequences
|
||||
? alignAndSuperpose(traceLocis)
|
||||
: superpose(traceLocis);
|
||||
? alignAndSuperpose(locis)
|
||||
: superpose(locis);
|
||||
|
||||
const eA = entries[0];
|
||||
for (let i = 1, il = traceLocis.length; i < il; ++i) {
|
||||
for (let i = 1, il = locis.length; i < il; ++i) {
|
||||
const eB = entries[i];
|
||||
const { bTransform, rmsd } = transforms[i - 1];
|
||||
await this.transform(eB.cell, bTransform);
|
||||
@@ -148,6 +150,7 @@ export class SuperpositionControls extends PurePluginUIComponent<{ }, Superposit
|
||||
const labelB = stripTags(eB.label);
|
||||
this.plugin.log.info(`Superposed [${labelA}] and [${labelB}] with RMSD ${rmsd.toFixed(2)}.`);
|
||||
}
|
||||
await this.cameraReset();
|
||||
};
|
||||
|
||||
superposeAtoms = async () => {
|
||||
@@ -171,26 +174,47 @@ export class SuperpositionControls extends PurePluginUIComponent<{ }, Superposit
|
||||
const count = entries[i].atoms.length;
|
||||
this.plugin.log.info(`Superposed ${count} ${count === 1 ? 'atom' : 'atoms'} of [${labelA}] and [${labelB}] with RMSD ${rmsd.toFixed(2)}.`);
|
||||
}
|
||||
await this.cameraReset();
|
||||
};
|
||||
|
||||
superposeDb = async () => {
|
||||
const input = this.plugin.managers.structure.hierarchy.behaviors.selection.value.structures;
|
||||
const traceOnly = this.state.options.traceOnly;
|
||||
|
||||
const transforms = alignAndSuperposeWithBestDatabaseMapping(input.map(s => s.cell.obj?.data!));
|
||||
const structures = input.map(s => s.cell.obj?.data!);
|
||||
const { entries, failedPairs, zeroOverlapPairs } = alignAndSuperposeWithSIFTSMapping(structures, { traceOnly });
|
||||
|
||||
let rmsd = 0;
|
||||
|
||||
for (const xform of transforms) {
|
||||
for (const xform of entries) {
|
||||
await this.transform(input[xform.other].cell, xform.transform.bTransform);
|
||||
rmsd += xform.transform.rmsd;
|
||||
}
|
||||
|
||||
rmsd /= Math.max(transforms.length - 1, 1);
|
||||
rmsd /= Math.max(entries.length - 1, 1);
|
||||
|
||||
this.plugin.log.info(`Superposed ${input.length} structures with avg. RMSD ${rmsd.toFixed(2)} Å.`);
|
||||
const formatPairs = (pairs: [number, number][]) => {
|
||||
return `[${pairs.map(([i, j]) => `(${structures[i].models[0].entryId}, ${structures[j].models[0].entryId})`).join(', ')}]`;
|
||||
};
|
||||
|
||||
if (zeroOverlapPairs.length) {
|
||||
this.plugin.log.warn(`Superposition: No UNIPROT mapping overlap between structures ${formatPairs(zeroOverlapPairs)}.`);
|
||||
}
|
||||
|
||||
if (failedPairs.length) {
|
||||
this.plugin.log.error(`Superposition: Failed to superpose structures ${formatPairs(failedPairs)}.`);
|
||||
}
|
||||
|
||||
if (entries.length) {
|
||||
this.plugin.log.info(`Superposed ${entries.length + 1} structures with avg. RMSD ${rmsd.toFixed(2)} Å.`);
|
||||
await this.cameraReset();
|
||||
}
|
||||
};
|
||||
|
||||
async cameraReset() {
|
||||
await new Promise(res => requestAnimationFrame(res));
|
||||
PluginCommands.Camera.Reset(this.plugin);
|
||||
};
|
||||
}
|
||||
|
||||
toggleByChains = () => this.setState({ action: this.state.action === 'byChains' ? void 0 : 'byChains' });
|
||||
toggleByAtoms = () => this.setState({ action: this.state.action === 'byAtoms' ? void 0 : 'byAtoms' });
|
||||
@@ -323,8 +347,8 @@ export class SuperpositionControls extends PurePluginUIComponent<{ }, Superposit
|
||||
|
||||
superposeByDbMapping() {
|
||||
return <>
|
||||
<Button icon={SuperposeChainsSvg} title='Superpose structures using database mapping.' className='msp-btn msp-btn-block' onClick={this.superposeDb} style={{ marginTop: '1px' }} disabled={this.state.isBusy}>
|
||||
DB
|
||||
<Button icon={SuperposeChainsSvg} title='Superpose structures using intersection of residues from SIFTS UNIPROT mapping.' className='msp-btn msp-btn-block' onClick={this.superposeDb} style={{ marginTop: '1px' }} disabled={this.state.isBusy}>
|
||||
Uniprot
|
||||
</Button>
|
||||
</>;
|
||||
}
|
||||
|
||||
@@ -77,9 +77,9 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea
|
||||
const rootCell = root && pivot.cell.parent.cells.get(root);
|
||||
|
||||
const simpleApply = rootCell && rootCell.status === 'error'
|
||||
? { header: 'Error enabling', icon: ErrorSvg, title: rootCell.errorText }
|
||||
? { header: !!rootCell.errorText && rootCell.errorText?.includes('404') ? 'No Density Data Available' : 'Error Enabling', icon: ErrorSvg, title: rootCell.errorText }
|
||||
: rootCell && rootCell.obj?.data.entries.length === 0
|
||||
? { header: 'Error enabling', icon: ErrorSvg, title: 'No entry for streaming found' }
|
||||
? { header: 'Error Enabling', icon: ErrorSvg, title: 'No Entry for Streaming Found' }
|
||||
: { header: 'Enable', icon: CheckSvg, title: 'Enable' };
|
||||
|
||||
return <ApplyActionControl state={pivot.cell.parent} action={InitVolumeStreaming} initiallyCollapsed={true} nodeRef={pivot.cell.transform.ref} simpleApply={simpleApply} />;
|
||||
|
||||
@@ -11,6 +11,6 @@ export { AccessibleSurfaceArea } from './custom-props/computed/accessible-surfac
|
||||
export { Interactions } from './custom-props/computed/interactions';
|
||||
export { SecondaryStructure } from './custom-props/computed/secondary-structure';
|
||||
export { ValenceModel } from './custom-props/computed/valence-model';
|
||||
export { BestDatabaseSequenceMapping } from './custom-props/sequence/best-database-mapping';
|
||||
export { SIFTSMapping as BestDatabaseSequenceMapping } from './custom-props/sequence/sifts-mapping';
|
||||
|
||||
export { CrossLinkRestraint } from './custom-props/integrative/cross-link-restraint';
|
||||
@@ -5,17 +5,17 @@
|
||||
*/
|
||||
|
||||
import { OrderedSet } from '../../../../../mol-data/int';
|
||||
import { BestDatabaseSequenceMapping as BestDatabaseSequenceMappingProp } from '../../../../../mol-model-props/sequence/best-database-mapping';
|
||||
import { BestDatabaseSequenceMappingColorThemeProvider } from '../../../../../mol-model-props/sequence/themes/best-database-mapping';
|
||||
import { SIFTSMapping as BestDatabaseSequenceMappingProp } from '../../../../../mol-model-props/sequence/sifts-mapping';
|
||||
import { SIFTSMappingColorThemeProvider } from '../../../../../mol-model-props/sequence/themes/sifts-mapping';
|
||||
import { Loci } from '../../../../../mol-model/loci';
|
||||
import { StructureElement } from '../../../../../mol-model/structure';
|
||||
import { ParamDefinition as PD } from '../../../../../mol-util/param-definition';
|
||||
import { PluginBehavior } from '../../../behavior';
|
||||
|
||||
export const BestDatabaseSequenceMapping = PluginBehavior.create<{ autoAttach: boolean, showTooltip: boolean }>({
|
||||
name: 'best-sequence-database-mapping-prop',
|
||||
export const SIFTSMapping = PluginBehavior.create<{ autoAttach: boolean, showTooltip: boolean }>({
|
||||
name: 'sifts-mapping-prop',
|
||||
category: 'custom-props',
|
||||
display: { name: 'Best Database Sequence Mapping' },
|
||||
display: { name: 'SIFTS Mapping' },
|
||||
ctor: class extends PluginBehavior.Handler<{ autoAttach: boolean, showTooltip: boolean }> {
|
||||
private provider = BestDatabaseSequenceMappingProp.Provider;
|
||||
|
||||
@@ -39,13 +39,13 @@ export const BestDatabaseSequenceMapping = PluginBehavior.create<{ autoAttach: b
|
||||
|
||||
register(): void {
|
||||
this.ctx.customModelProperties.register(this.provider, this.params.autoAttach);
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.add(BestDatabaseSequenceMappingColorThemeProvider);
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.add(SIFTSMappingColorThemeProvider);
|
||||
this.ctx.managers.lociLabels.addProvider(this.labelProvider);
|
||||
}
|
||||
|
||||
unregister() {
|
||||
this.ctx.customModelProperties.unregister(this.provider.descriptor.name);
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.remove(BestDatabaseSequenceMappingColorThemeProvider);
|
||||
this.ctx.representation.structure.themes.colorThemeRegistry.remove(SIFTSMappingColorThemeProvider);
|
||||
this.ctx.managers.lociLabels.removeProvider(this.labelProvider);
|
||||
}
|
||||
},
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2022 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>
|
||||
@@ -27,11 +27,19 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => {
|
||||
expandRadius: PD.Numeric(5, { min: 1, max: 10, step: 1 }),
|
||||
targetParams: PD.Group(reprParams, {
|
||||
label: 'Target',
|
||||
customDefault: createStructureRepresentationParams(plugin, void 0, { type: 'ball-and-stick', size: 'physical', typeParams: { sizeFactor: 0.26, alpha: 0.51, adjustCylinderLength: true } })
|
||||
customDefault: createStructureRepresentationParams(plugin, void 0, {
|
||||
type: 'ball-and-stick',
|
||||
size: 'physical',
|
||||
typeParams: { sizeFactor: 0.22, sizeAspectRatio: 0.73, adjustCylinderLength: true, xrayShaded: true, aromaticBonds: false, multipleBonds: 'off', excludeTypes: ['hydrogen-bond', 'metal-coordination'] },
|
||||
})
|
||||
}),
|
||||
surroundingsParams: PD.Group(reprParams, {
|
||||
label: 'Surroundings',
|
||||
customDefault: createStructureRepresentationParams(plugin, void 0, { type: 'ball-and-stick', size: 'physical', typeParams: { sizeFactor: 0.16 } })
|
||||
customDefault: createStructureRepresentationParams(plugin, void 0, {
|
||||
type: 'ball-and-stick',
|
||||
size: 'physical',
|
||||
typeParams: { sizeFactor: 0.16, excludeTypes: ['hydrogen-bond', 'metal-coordination'] }
|
||||
})
|
||||
}),
|
||||
nciParams: PD.Group(reprParams, {
|
||||
label: 'Non-covalent Int.',
|
||||
@@ -44,6 +52,7 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => {
|
||||
components: PD.MultiSelect(FocusComponents, PD.arrayToOptions(FocusComponents)),
|
||||
excludeTargetFromSurroundings: PD.Boolean(false, { label: 'Exclude Target', description: 'Exclude the focus "target" from the surroudings component.' }),
|
||||
ignoreHydrogens: PD.Boolean(false),
|
||||
ignoreLight: PD.Boolean(false),
|
||||
material: Material.getParam(),
|
||||
clip: PD.Group(Clip.Params),
|
||||
};
|
||||
@@ -68,10 +77,10 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
|
||||
|
||||
private getReprParams(reprParams: PD.Values<PD.Params>) {
|
||||
return {
|
||||
...this.params.targetParams,
|
||||
...reprParams,
|
||||
type: {
|
||||
name: reprParams.type.name,
|
||||
params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, material: this.params.material, clip: this.params.clip }
|
||||
params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, ignoreLight: this.params.ignoreLight, material: this.params.material, clip: this.params.clip }
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -114,7 +123,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
|
||||
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;
|
||||
.apply(StateTransforms.Representation.StructureRepresentation3D, this.getReprParams(this.params.nciParams), { tags: StructureFocusRepresentationTags.SurrNciRepr }).ref;
|
||||
}
|
||||
|
||||
return { state, builder, refs };
|
||||
@@ -216,7 +225,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
|
||||
hasComponent = components.indexOf('interactions') >= 0;
|
||||
for (const repr of state.select(all.withTag(StructureFocusRepresentationTags.SurrNciRepr))) {
|
||||
if (!hasComponent) builder.delete(repr.transform.ref);
|
||||
else builder.to(repr).update(this.params.nciParams);
|
||||
else builder.to(repr).update(this.getReprParams(this.params.nciParams));
|
||||
}
|
||||
|
||||
await PluginCommands.State.Update(this.plugin, { state, tree: builder, options: { doNotLogTiming: true, doNotUpdateCurrent: true } });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -35,7 +35,7 @@ export const CartoonParams = {
|
||||
...NucleotideRingParams,
|
||||
...PolymerDirectionParams,
|
||||
sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }),
|
||||
visuals: PD.MultiSelect(['polymer-trace', 'polymer-gap', 'nucleotide-block'], PD.objectToOptions(CartoonVisuals)),
|
||||
visuals: PD.MultiSelect(['polymer-trace', 'polymer-gap', 'nucleotide-ring'], PD.objectToOptions(CartoonVisuals)),
|
||||
bumpFrequency: PD.Numeric(2, { min: 0, max: 10, step: 0.1 }, BaseGeometry.ShadingCategory),
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ export function getCartoonParams(ctx: ThemeRegistryContext, structure: Structure
|
||||
if (!hasGaps && u.gapElements.length) hasGaps = true;
|
||||
});
|
||||
params.visuals.defaultValue = ['polymer-trace'];
|
||||
if (hasNucleotides) params.visuals.defaultValue.push('nucleotide-block');
|
||||
if (hasNucleotides) params.visuals.defaultValue.push('nucleotide-ring');
|
||||
if (hasGaps) params.visuals.defaultValue.push('polymer-gap');
|
||||
return params;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user