Browse Source

Merge branch 'master' into structure-mol-surf

Alexander Rose 2 years ago
parent
commit
ef838a1b83

+ 1 - 0
CHANGELOG.md

@@ -9,6 +9,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Excluded common protein caps `NME` and `ACE` from the ligand selection query
 - Add screen-space shadow post-processing effect
 - Add "Structure Molecular Surface" visual
+- Add `external-volume` theme (coloring of arbitrary geometries by user-selected volume)
 
 ## [v3.25.1] - 2022-11-20
 

File diff suppressed because it is too large
+ 344 - 203
package-lock.json


+ 18 - 18
package.json

@@ -98,52 +98,52 @@
   "license": "MIT",
   "devDependencies": {
     "@graphql-codegen/add": "^3.2.1",
-    "@graphql-codegen/cli": "^2.13.11",
+    "@graphql-codegen/cli": "^2.15.0",
     "@graphql-codegen/time": "^3.2.1",
-    "@graphql-codegen/typescript": "^2.8.1",
+    "@graphql-codegen/typescript": "^2.8.3",
     "@graphql-codegen/typescript-graphql-files-modules": "^2.2.1",
     "@graphql-codegen/typescript-graphql-request": "^4.5.8",
-    "@graphql-codegen/typescript-operations": "^2.5.6",
+    "@graphql-codegen/typescript-operations": "^2.5.8",
     "@types/cors": "^2.8.12",
-    "@types/gl": "^6.0.1",
-    "@types/jest": "^29.2.2",
-    "@types/react": "^18.0.25",
-    "@types/react-dom": "^18.0.8",
-    "@typescript-eslint/eslint-plugin": "^5.42.1",
-    "@typescript-eslint/parser": "^5.42.1",
+    "@types/gl": "^6.0.2",
+    "@types/jest": "^29.2.3",
+    "@types/react": "^18.0.26",
+    "@types/react-dom": "^18.0.9",
+    "@typescript-eslint/eslint-plugin": "^5.45.0",
+    "@typescript-eslint/parser": "^5.45.0",
     "benchmark": "^2.1.4",
-    "concurrently": "^7.5.0",
+    "concurrently": "^7.6.0",
     "cpx2": "^4.2.0",
     "crypto-browserify": "^3.12.0",
     "css-loader": "^6.7.2",
-    "eslint": "^8.27.0",
+    "eslint": "^8.29.0",
     "extra-watch-webpack-plugin": "^1.0.3",
     "file-loader": "^6.2.0",
-    "fs-extra": "^10.1.0",
+    "fs-extra": "^11.1.0",
     "graphql": "^16.6.0",
     "http-server": "^14.1.1",
     "jest": "^29.3.1",
-    "mini-css-extract-plugin": "^2.6.1",
+    "mini-css-extract-plugin": "^2.7.1",
     "path-browserify": "^1.0.1",
     "raw-loader": "^4.0.2",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "sass": "^1.56.1",
     "sass-loader": "^13.2.0",
-    "simple-git": "^3.15.0",
+    "simple-git": "^3.15.1",
     "stream-browserify": "^3.0.0",
     "style-loader": "^3.3.1",
     "ts-jest": "^29.0.3",
-    "typescript": "^4.8.4",
+    "typescript": "^4.9.3",
     "webpack": "^5.75.0",
-    "webpack-cli": "^4.10.0"
+    "webpack-cli": "^5.0.0"
   },
   "dependencies": {
     "@types/argparse": "^2.0.10",
     "@types/benchmark": "^2.1.2",
     "@types/compression": "1.7.2",
     "@types/express": "^4.17.14",
-    "@types/node": "^16.18.3",
+    "@types/node": "^16.18.4",
     "@types/node-fetch": "^2.6.2",
     "@types/swagger-ui-dist": "3.30.1",
     "argparse": "^2.0.1",
@@ -155,7 +155,7 @@
     "immer": "^9.0.16",
     "immutable": "^4.1.0",
     "node-fetch": "^2.6.7",
-    "rxjs": "^7.5.7",
+    "rxjs": "^7.6.0",
     "swagger-ui-dist": "^4.15.5",
     "tslib": "^2.4.1",
     "util.promisify": "^1.1.1",

+ 200 - 27
src/extensions/rcsb/graphql/types.ts

@@ -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-08-20T16:36:05-07:00
+// Generated on 2022-12-03T21:55:37-08:00
 
 /** All built-in and custom scalars, mapped to their actual values */
 export type Scalars = {
@@ -343,6 +343,14 @@ export type Citation = {
    *
    */
   readonly journal_abbrev?: Maybe<Scalars['String']>;
+  /**
+   * Full name of the cited journal; relevant for journal articles.
+   *
+   * Examples:
+   * Journal of Molecular Biology
+   *
+   */
+  readonly journal_full?: Maybe<Scalars['String']>;
   /**
    * The American Society for Testing and Materials (ASTM) code
    *  assigned to the journal cited (also referred to as the CODEN
@@ -550,6 +558,7 @@ export type CoreBranchedEntityInstance = {
   readonly rcsb_id: Scalars['String'];
   readonly rcsb_latest_revision?: Maybe<RcsbLatestRevision>;
   readonly rcsb_ligand_neighbors?: Maybe<ReadonlyArray<Maybe<RcsbLigandNeighbors>>>;
+  readonly struct_asym?: Maybe<StructAsym>;
 };
 
 export type CoreChemComp = {
@@ -661,6 +670,7 @@ export type CoreEntry = {
   readonly exptl?: Maybe<ReadonlyArray<Maybe<Exptl>>>;
   readonly exptl_crystal?: Maybe<ReadonlyArray<Maybe<ExptlCrystal>>>;
   readonly exptl_crystal_grow?: Maybe<ReadonlyArray<Maybe<ExptlCrystalGrow>>>;
+  readonly ma_data?: Maybe<ReadonlyArray<Maybe<MaData>>>;
   /** Get all non-polymer (non-solvent) entities for this PDB entry. */
   readonly nonpolymer_entities?: Maybe<ReadonlyArray<Maybe<CoreNonpolymerEntity>>>;
   readonly pdbx_SG_project?: Maybe<ReadonlyArray<Maybe<PdbxSgProject>>>;
@@ -701,6 +711,7 @@ export type CoreEntry = {
   /** The list of content types associated with this entry. */
   readonly rcsb_associated_holdings?: Maybe<CurrentEntry>;
   readonly rcsb_binding_affinity?: Maybe<ReadonlyArray<Maybe<RcsbBindingAffinity>>>;
+  readonly rcsb_comp_model_provenance?: Maybe<RcsbCompModelProvenance>;
   readonly rcsb_entry_container_identifiers: RcsbEntryContainerIdentifiers;
   readonly rcsb_entry_group_membership?: Maybe<ReadonlyArray<Maybe<RcsbEntryGroupMembership>>>;
   readonly rcsb_entry_info: RcsbEntryInfo;
@@ -713,6 +724,7 @@ export type CoreEntry = {
    *
    */
   readonly rcsb_id: Scalars['String'];
+  readonly rcsb_ma_qa_metric_global?: Maybe<ReadonlyArray<Maybe<RcsbMaQaMetricGlobal>>>;
   readonly rcsb_primary_citation?: Maybe<RcsbPrimaryCitation>;
   readonly refine?: Maybe<ReadonlyArray<Maybe<Refine>>>;
   readonly refine_analyze?: Maybe<ReadonlyArray<Maybe<RefineAnalyze>>>;
@@ -786,6 +798,7 @@ export type CoreNonpolymerEntityInstance = {
   readonly rcsb_nonpolymer_instance_validation_score?: Maybe<ReadonlyArray<Maybe<RcsbNonpolymerInstanceValidationScore>>>;
   readonly rcsb_nonpolymer_struct_conn?: Maybe<ReadonlyArray<Maybe<RcsbNonpolymerStructConn>>>;
   readonly rcsb_target_neighbors?: Maybe<ReadonlyArray<Maybe<RcsbTargetNeighbors>>>;
+  readonly struct_asym?: Maybe<StructAsym>;
 };
 
 export type CorePfam = {
@@ -919,6 +932,7 @@ export type CorePolymerEntityInstance = {
   readonly rcsb_polymer_instance_feature?: Maybe<ReadonlyArray<Maybe<RcsbPolymerInstanceFeature>>>;
   readonly rcsb_polymer_instance_feature_summary?: Maybe<ReadonlyArray<Maybe<RcsbPolymerInstanceFeatureSummary>>>;
   readonly rcsb_polymer_struct_conn?: Maybe<ReadonlyArray<Maybe<RcsbPolymerStructConn>>>;
+  readonly struct_asym?: Maybe<StructAsym>;
 };
 
 export type CorePubmed = {
@@ -1284,9 +1298,9 @@ export type Em2dCrystalEntity = {
   readonly id: Scalars['String'];
   /** pointer to _em_image_processing.id in the EM_IMAGE_PROCESSING category. */
   readonly image_processing_id: Scalars['String'];
-  /** Unit-cell length a in Angstroms. */
+  /** Unit-cell length a in angstroms. */
   readonly length_a?: Maybe<Scalars['Float']>;
-  /** Unit-cell length b in Angstroms. */
+  /** Unit-cell length b in angstroms. */
   readonly length_b?: Maybe<Scalars['Float']>;
   /** Thickness of 2D crystal */
   readonly length_c?: Maybe<Scalars['Float']>;
@@ -1317,11 +1331,11 @@ export type Em3dCrystalEntity = {
   readonly id: Scalars['String'];
   /** pointer to _em_image_processing.id in the EM_IMAGE_PROCESSING category. */
   readonly image_processing_id: Scalars['String'];
-  /** Unit-cell length a in Angstroms. */
+  /** Unit-cell length a in angstroms. */
   readonly length_a?: Maybe<Scalars['Float']>;
-  /** Unit-cell length b in Angstroms. */
+  /** Unit-cell length b in angstroms. */
   readonly length_b?: Maybe<Scalars['Float']>;
-  /** Unit-cell length c in Angstroms. */
+  /** Unit-cell length c in angstroms. */
   readonly length_c?: Maybe<Scalars['Float']>;
   /**
    * Space group name.
@@ -1482,7 +1496,7 @@ export type Em3dReconstruction = {
    */
   readonly refinement_type?: Maybe<Scalars['String']>;
   /**
-   * The final resolution (in Angstroms)of the 3D reconstruction.
+   * The final resolution (in angstroms)of the 3D reconstruction.
    *
    * Examples:
    * null, null
@@ -1558,7 +1572,7 @@ export type EmDiffractionShell = {
    */
   readonly fourier_space_coverage?: Maybe<Scalars['Float']>;
   /**
-   * High resolution limit for this shell (Angstroms)
+   * High resolution limit for this shell (angstroms)
    *
    * Examples:
    * null
@@ -1568,7 +1582,7 @@ export type EmDiffractionShell = {
   /** Unique identifier for the category em_diffraction_shell */
   readonly id: Scalars['String'];
   /**
-   * Low resolution limit for this shell (Angstroms)
+   * Low resolution limit for this shell (angstroms)
    *
    * Examples:
    * null
@@ -1614,7 +1628,7 @@ export type EmDiffractionStats = {
    */
   readonly fourier_space_coverage?: Maybe<Scalars['Float']>;
   /**
-   * High resolution limit of the structure factor data, in Angstroms
+   * High resolution limit of the structure factor data, in angstroms
    *
    * Examples:
    * null
@@ -1998,12 +2012,12 @@ export type EmImaging = {
   /** The magnification indicated by the microscope readout. */
   readonly nominal_magnification?: Maybe<Scalars['Int']>;
   /**
-   * The specimen temperature maximum (degrees Kelvin) for the duration
+   * The specimen temperature maximum (kelvin) for the duration
    *  of imaging.
    */
   readonly recording_temperature_maximum?: Maybe<Scalars['Float']>;
   /**
-   * The specimen temperature minimum (degrees Kelvin) for the duration
+   * The specimen temperature minimum (kelvin) for the duration
    *  of imaging.
    */
   readonly recording_temperature_minimum?: Maybe<Scalars['Float']>;
@@ -2028,7 +2042,7 @@ export type EmImaging = {
   /** Foreign key to the EM_SPECIMEN category */
   readonly specimen_id?: Maybe<Scalars['String']>;
   /**
-   * The mean specimen stage temperature (degrees Kelvin) during imaging
+   * The mean specimen stage temperature (in kelvin) during imaging
    *  in the microscope.
    */
   readonly temperature?: Maybe<Scalars['Float']>;
@@ -2215,7 +2229,7 @@ export type EmStaining = {
 };
 
 export type EmVitrification = {
-  /** The temperature (in degrees Kelvin) of the sample just prior to vitrification. */
+  /** The temperature (in kelvin) of the sample just prior to vitrification. */
   readonly chamber_temperature?: Maybe<Scalars['Float']>;
   /**
    * This is the name of the cryogen.
@@ -2259,7 +2273,7 @@ export type EmVitrification = {
   /** This data item is a pointer to _em_specimen.id */
   readonly specimen_id: Scalars['String'];
   /**
-   * The vitrification temperature (in degrees Kelvin), e.g.,
+   * The vitrification temperature (in kelvin), e.g.,
    *   temperature of the plunge instrument cryogen bath.
    */
   readonly temp?: Maybe<Scalars['Float']>;
@@ -2364,6 +2378,14 @@ export type EntityPoly = {
    *
    */
   readonly pdbx_seq_one_letter_code_can?: Maybe<Scalars['String']>;
+  /**
+   * Evidence for the assignment of the polymer sequence.
+   *
+   * Allowable values:
+   * depositor provided, derived from coordinates
+   *
+   */
+  readonly pdbx_sequence_evidence_code?: Maybe<Scalars['String']>;
   /**
    * The PDB strand/chain id(s) corresponding to this polymer entity.
    *
@@ -3005,6 +3027,8 @@ export type Entry = {
    *  identifier.
    */
   readonly id: Scalars['String'];
+  /** An identifier for the model collection associated with the entry. */
+  readonly ma_collection_id?: Maybe<Scalars['String']>;
 };
 
 export type Exptl = {
@@ -3263,6 +3287,29 @@ export type InterfacePartnerFeatureFeaturePositions = {
   readonly values?: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
 };
 
+export type MaData = {
+  /**
+   * The type of data held in the dataset.
+   *
+   * Allowable values:
+   * coevolution MSA, input structure, model coordinates, other, polymeric template library, spatial restraints, target, target-template alignment, template structure
+   *
+   */
+  readonly content_type?: Maybe<Scalars['String']>;
+  /** Details for other content types. */
+  readonly content_type_other_details?: Maybe<Scalars['String']>;
+  /** A unique identifier for the data. */
+  readonly id: Scalars['Int'];
+  /**
+   * An author-given name for the content held in the dataset.
+   *
+   * Examples:
+   * NMR NOE Distances, Target Template Alignment, Coevolution Data
+   *
+   */
+  readonly name?: Maybe<Scalars['String']>;
+};
+
 export type MethodDetails = {
   /** A description of special aspects of the clustering process */
   readonly description?: Maybe<Scalars['String']>;
@@ -4199,7 +4246,7 @@ export type PdbxNmrExptlSampleConditions = {
    */
   readonly pressure_units?: Maybe<Scalars['String']>;
   /**
-   * The temperature (in Kelvin) at which NMR data were
+   * The temperature (in kelvin) at which NMR data were
    *  collected.
    */
   readonly temperature?: Maybe<Scalars['String']>;
@@ -4453,7 +4500,7 @@ export type PdbxPrdAudit = {
    * An identifier for the wwPDB site creating or modifying the molecule.
    *
    * Allowable values:
-   * BMRB, PDBC, PDBJ, PDBe, RCSB
+   * BMRB, PDBC, PDBE, PDBJ, RCSB
    *
    */
   readonly processing_site?: Maybe<Scalars['String']>;
@@ -6817,7 +6864,7 @@ export type Query = {
   readonly assemblies?: Maybe<ReadonlyArray<Maybe<CoreAssembly>>>;
   /** Get an assembly given the PDB ID and ASSEMBLY ID. Here ASSEMBLY ID is '1', '2', '3', etc. or 'deposited' for deposited coordinates. */
   readonly assembly?: Maybe<CoreAssembly>;
-  /** Get a list of PDB branched entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. */
+  /** Get a list of PDB branched entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. Note that the ENTRY ID part must be upper case. */
   readonly branched_entities?: Maybe<ReadonlyArray<Maybe<CoreBranchedEntity>>>;
   /** Get a PDB branched entity, given the PDB ID and ENTITY ID. Here ENTITY ID is a '1', '2', '3', etc. */
   readonly branched_entity?: Maybe<CoreBranchedEntity>;
@@ -6841,9 +6888,9 @@ export type Query = {
   readonly group_provenance?: Maybe<GroupProvenance>;
   /** Get a pairwise polymeric interface given the PDB ID, ASSEMBLY ID and INTERFACE ID. */
   readonly interface?: Maybe<CoreInterface>;
-  /** Get a list of pairwise polymeric interfaces given a list of INTERFACE IDs. Here INTERFACE ID is a compound identifier that includes entry_id, assembly_id and interface_id e.g. 1XXX-1.1. */
+  /** Get a list of pairwise polymeric interfaces given a list of INTERFACE IDs. Here INTERFACE ID is a compound identifier that includes entry_id, assembly_id and interface_id e.g. 1XXX-1.1. Note that the ENTRY ID part must be upper case. */
   readonly interfaces?: Maybe<ReadonlyArray<Maybe<CoreInterface>>>;
-  /** Get a list of PDB non-polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. */
+  /** Get a list of PDB non-polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. Note that the ENTRY ID part must be upper case. */
   readonly nonpolymer_entities?: Maybe<ReadonlyArray<Maybe<CoreNonpolymerEntity>>>;
   /** Get a PDB non-polymer entity, given the PDB ID and ENTITY ID. Here ENTITY ID is a '1', '2', '3', etc. */
   readonly nonpolymer_entity?: Maybe<CoreNonpolymerEntity>;
@@ -6851,7 +6898,7 @@ export type Query = {
   readonly nonpolymer_entity_instance?: Maybe<CoreNonpolymerEntityInstance>;
   /** Get a list of PDB non-polymer entity instances (chains), given the list of ENTITY INSTANCE IDs. Here ENTITY INSTANCE ID identifies structural element in the asymmetric unit, e.g. 'A', 'B', etc. */
   readonly nonpolymer_entity_instances?: Maybe<ReadonlyArray<Maybe<CoreNonpolymerEntityInstance>>>;
-  /** Get a list of PDB polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. */
+  /** Get a list of PDB polymer entities given a list of ENTITY IDs. Here ENTITY ID is a compound identifier that includes entry_id and entity_id separated by '_', e.g. 1XXX_1. Note that the ENTRY ID part must be upper case. */
   readonly polymer_entities?: Maybe<ReadonlyArray<Maybe<CorePolymerEntity>>>;
   /** Get a PDB polymer entity, given the PDB ID and ENTITY ID. Here ENTITY ID is a '1', '2', '3', etc. */
   readonly polymer_entity?: Maybe<CorePolymerEntity>;
@@ -8421,6 +8468,29 @@ export type RcsbClusterMembership = {
   readonly identity?: Maybe<Scalars['Int']>;
 };
 
+export type RcsbCompModelProvenance = {
+  /**
+   * Entry identifier corresponding to the computed structure model.
+   *
+   * Examples:
+   * AF-P60325-F1, ma-bak-cepc-0019
+   *
+   */
+  readonly entry_id: Scalars['String'];
+  /**
+   * Source database for the computed structure model.
+   *
+   * Allowable values:
+   * AlphaFoldDB, ModelArchive
+   *
+   */
+  readonly source_db?: Maybe<Scalars['String']>;
+  /** Source filename for the computed structure model. */
+  readonly source_filename?: Maybe<Scalars['String']>;
+  /** Source URL for computed structure model file. */
+  readonly source_url?: Maybe<Scalars['String']>;
+};
+
 export type RcsbEntityHostOrganism = {
   /**
    * The beginning polymer sequence position for the polymer section corresponding
@@ -8657,7 +8727,7 @@ export type RcsbEntitySourceOrganism = {
    * A code indicating the provenance of the source organism details for the entity
    *
    * Allowable values:
-   * PDB Primary Data
+   * PDB Primary Data, UniProt
    *
    */
   readonly provenance_source?: Maybe<Scalars['String']>;
@@ -8731,7 +8801,7 @@ export type RcsbEntryContainerIdentifiers = {
    * Entry identifier for the container.
    *
    * Examples:
-   * 1KIP, 4HHB
+   * 4HHB, AF_AFP60325F1, MA_MABAKCEPC0019
    *
    */
   readonly entry_id: Scalars['String'];
@@ -8879,6 +8949,15 @@ export type RcsbEntryInfo = {
    *
    */
   readonly na_polymer_entity_types?: Maybe<Scalars['String']>;
+  /**
+   * This data item identifies secondary structure
+   *  features of nucleic acids in the entry.
+   *
+   * Allowable values:
+   * a-form double helix, b-form double helix, bulge loop, double helix, four-way junction, hairpin loop, internal loop, mismatched base pair, other right-handed double helix, parallel strands, quadruple helix, tetraloop, three-way junction, triple helix, two-way junction, z-form double helix
+   *
+   */
+  readonly ndb_struct_conf_na_feature_combined?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
   /** Bound nonpolymer components in this entry. */
   readonly nonpolymer_bound_components?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
   /** The number of distinct non-polymer entities in the structure entry exclusive of solvent. */
@@ -8955,6 +9034,21 @@ export type RcsbEntryInfo = {
   readonly software_programs_combined?: Maybe<ReadonlyArray<Maybe<Scalars['String']>>>;
   /** The number of distinct solvent entities per deposited structure model. */
   readonly solvent_entity_count?: Maybe<Scalars['Int']>;
+  /**
+   * Indicates if the structure was determined using experimental or computational methods.
+   *
+   * Allowable values:
+   * computational, experimental
+   *
+   */
+  readonly structure_determination_methodology: Scalars['String'];
+  /**
+   * Indicates the priority of the value in _rcsb_entry_info.structure_determination_methodology.
+   *  The lower the number the higher the priority.
+   *  Priority values for "experimental" structures is currently set to 10 and
+   *  the values for "computational" structures is set to 100.
+   */
+  readonly structure_determination_methodology_priority?: Maybe<Scalars['Int']>;
 };
 
 export type RcsbEntryInfoDiffrnResolutionHigh = {
@@ -9294,6 +9388,49 @@ export type RcsbLigandNeighbors = {
   readonly seq_id?: Maybe<Scalars['Int']>;
 };
 
+export type RcsbMaQaMetricGlobal = {
+  readonly ma_qa_metric_global?: Maybe<ReadonlyArray<Maybe<RcsbMaQaMetricGlobalMaQaMetricGlobal>>>;
+  /** The model identifier. */
+  readonly model_id: Scalars['Int'];
+};
+
+export type RcsbMaQaMetricGlobalMaQaMetricGlobal = {
+  /**
+   * Description of the global QA metric.
+   *
+   * Examples:
+   * confidence score predicting accuracy according to the CA-only Local Distance Difference Test (lDDT-CA) in [0,100]
+   *
+   */
+  readonly description?: Maybe<Scalars['String']>;
+  /**
+   * Name of the global QA metric.
+   *
+   * Examples:
+   * pLDDT
+   *
+   */
+  readonly name: Scalars['String'];
+  /**
+   * The type of global QA metric.
+   *
+   * Allowable values:
+   * PAE, contact probability, distance, energy, ipTM, normalized score, other, pLDDT, pLDDT all-atom, pLDDT all-atom in [0,1], pLDDT in [0,1], pTM, zscore
+   *
+   */
+  readonly type: Scalars['String'];
+  /** Details for other type of global QA metric. */
+  readonly type_other_details?: Maybe<Scalars['String']>;
+  /**
+   * Value of the global QA metric.
+   *
+   * Examples:
+   * null
+   *
+   */
+  readonly value: Scalars['Float'];
+};
+
 export type RcsbMembraneLineage = {
   /** Hierarchy depth. */
   readonly depth?: Maybe<Scalars['Int']>;
@@ -10332,7 +10469,7 @@ export type RcsbPolymerEntityContainerIdentifiersReferenceSequenceIdentifiers =
    * Source of the reference database assignment
    *
    * Allowable values:
-   * PDB, RCSB, SIFTS
+   * PDB, RCSB, SIFTS, UniProt
    *
    */
   readonly provenance_source?: Maybe<Scalars['String']>;
@@ -10737,7 +10874,7 @@ export type RcsbPolymerInstanceFeature = {
    * A type or category of the feature.
    *
    * Allowable values:
-   * ANGLE_OUTLIER, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SCOP, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ, ASA
+   * ANGLE_OUTLIER, BEND, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, HELX_LH_PP_P, HELX_RH_3T_P, HELX_RH_AL_P, HELX_RH_PI_P, MA_QA_METRIC_LOCAL_TYPE_CONTACT_PROBABILITY, MA_QA_METRIC_LOCAL_TYPE_DISTANCE, MA_QA_METRIC_LOCAL_TYPE_ENERGY, MA_QA_METRIC_LOCAL_TYPE_IPTM, MA_QA_METRIC_LOCAL_TYPE_NORMALIZED_SCORE, MA_QA_METRIC_LOCAL_TYPE_OTHER, MA_QA_METRIC_LOCAL_TYPE_PAE, MA_QA_METRIC_LOCAL_TYPE_PLDDT, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM_[0,1], MA_QA_METRIC_LOCAL_TYPE_PLDDT_[0,1], MA_QA_METRIC_LOCAL_TYPE_PTM, MA_QA_METRIC_LOCAL_TYPE_ZSCORE, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SCOP, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, STRN, TURN_TY1_P, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ, ASA
    *
    */
   readonly type?: Maybe<Scalars['String']>;
@@ -10748,7 +10885,7 @@ export type RcsbPolymerInstanceFeatureAdditionalProperties = {
    * The additional property name.
    *
    * Allowable values:
-   * CATH_DOMAIN_ID, CATH_NAME, ECOD_DOMAIN_ID, ECOD_FAMILY_NAME, OMEGA_ANGLE, PARTNER_ASYM_ID, PARTNER_BOND_DISTANCE, PARTNER_COMP_ID, SCOP2_DOMAIN_ID, SCOP2_FAMILY_ID, SCOP2_FAMILY_NAME, SCOP2_SUPERFAMILY_ID, SCOP2_SUPERFAMILY_NAME, SCOP_DOMAIN_ID, SCOP_NAME, SCOP_SUN_ID, SHEET_SENSE
+   * CATH_DOMAIN_ID, CATH_NAME, ECOD_DOMAIN_ID, ECOD_FAMILY_NAME, MODELCIF_MODEL_ID, OMEGA_ANGLE, PARTNER_ASYM_ID, PARTNER_BOND_DISTANCE, PARTNER_COMP_ID, SCOP2_DOMAIN_ID, SCOP2_FAMILY_ID, SCOP2_FAMILY_NAME, SCOP2_SUPERFAMILY_ID, SCOP2_SUPERFAMILY_NAME, SCOP_DOMAIN_ID, SCOP_NAME, SCOP_SUN_ID, SHEET_SENSE
    *
    */
   readonly name?: Maybe<Scalars['String']>;
@@ -10818,7 +10955,7 @@ export type RcsbPolymerInstanceFeatureSummary = {
    * Type or category of the feature.
    *
    * Allowable values:
-   * ANGLE_OUTLIER, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SAbDab Antibody Heavy Chain Subclass, SAbDab Antibody Light Chain Subclass, SAbDab Antibody Light Chain Type, SCOP, SCOP2 Family, SCOP2 Superfamily, SCOP2B Superfamily, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ
+   * ANGLE_OUTLIER, BEND, BINDING_SITE, BOND_OUTLIER, C-MANNOSYLATION_SITE, CATH, CIS-PEPTIDE, ECOD, HELIX_P, HELX_LH_PP_P, HELX_RH_3T_P, HELX_RH_AL_P, HELX_RH_PI_P, MA_QA_METRIC_LOCAL_TYPE_CONTACT_PROBABILITY, MA_QA_METRIC_LOCAL_TYPE_DISTANCE, MA_QA_METRIC_LOCAL_TYPE_ENERGY, MA_QA_METRIC_LOCAL_TYPE_IPTM, MA_QA_METRIC_LOCAL_TYPE_NORMALIZED_SCORE, MA_QA_METRIC_LOCAL_TYPE_OTHER, MA_QA_METRIC_LOCAL_TYPE_PAE, MA_QA_METRIC_LOCAL_TYPE_PLDDT, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM, MA_QA_METRIC_LOCAL_TYPE_PLDDT_ALL-ATOM_[0,1], MA_QA_METRIC_LOCAL_TYPE_PLDDT_[0,1], MA_QA_METRIC_LOCAL_TYPE_PTM, MA_QA_METRIC_LOCAL_TYPE_ZSCORE, MEMBRANE_SEGMENT, MOGUL_ANGLE_OUTLIER, MOGUL_BOND_OUTLIER, N-GLYCOSYLATION_SITE, O-GLYCOSYLATION_SITE, RAMACHANDRAN_OUTLIER, ROTAMER_OUTLIER, RSCC_OUTLIER, RSRZ_OUTLIER, S-GLYCOSYLATION_SITE, SABDAB_ANTIBODY_HEAVY_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_SUBCLASS, SABDAB_ANTIBODY_LIGHT_CHAIN_TYPE, SCOP, SCOP2B_SUPERFAMILY, SCOP2_FAMILY, SCOP2_SUPERFAMILY, SHEET, STEREO_OUTLIER, STRN, TURN_TY1_P, UNASSIGNED_SEC_STRUCT, UNOBSERVED_ATOM_XYZ, UNOBSERVED_RESIDUE_XYZ, ZERO_OCCUPANCY_ATOM_XYZ, ZERO_OCCUPANCY_RESIDUE_XYZ
    *
    */
   readonly type?: Maybe<Scalars['String']>;
@@ -13377,6 +13514,11 @@ export type ReflnsShell = {
 };
 
 export type Software = {
+  /**
+   * This data item is a pointer to _citation.id in the CITATION
+   *  category.
+   */
+  readonly citation_id?: Maybe<Scalars['String']>;
   /**
    * The classification of the program according to its
    *  major function.
@@ -13527,6 +13669,37 @@ export type Struct = {
   readonly title?: Maybe<Scalars['String']>;
 };
 
+export type StructAsym = {
+  /**
+   * This data item is a pointer to _atom_site.pdbx_PDB_strand_id the
+   *  ATOM_SITE category.
+   *
+   * Examples:
+   * 1ABC
+   *
+   */
+  readonly pdbx_PDB_id?: Maybe<Scalars['String']>;
+  /**
+   * This data item is a pointer to _atom_site.ndb_alias_strand_id the
+   *  ATOM_SITE category.
+   */
+  readonly pdbx_alt_id?: Maybe<Scalars['String']>;
+  /**
+   * This data item gives the order of the structural elements in the
+   *  ATOM_SITE category.
+   */
+  readonly pdbx_order?: Maybe<Scalars['Int']>;
+  /**
+   * This data item describes the general type of the structural elements
+   *  in the ATOM_SITE category.
+   *
+   * Allowable values:
+   * ATOMN, ATOMP, ATOMS, HETAC, HETAD, HETAI, HETAIN, HETAS, HETIC
+   *
+   */
+  readonly pdbx_type?: Maybe<Scalars['String']>;
+};
+
 export type StructKeywords = {
   /**
    * Terms characterizing the macromolecular structure.

+ 2 - 2
src/mol-canvas3d/passes/postprocessing.ts

@@ -343,9 +343,9 @@ export const PostprocessingParams = {
     }, { cycle: true, description: 'Darken occluded crevices with the ambient occlusion effect' }),
     shadow: PD.MappedStatic('off', {
         on: PD.Group({
-            steps: PD.Numeric(1, { min: 1, max: 20, step: 1 }),
+            steps: PD.Numeric(1, { min: 1, max: 64, step: 1 }),
             bias: PD.Numeric(0.6, { min: 0.0, max: 1.0, step: 0.01 }),
-            maxDistance: PD.Numeric(3.0, { min: 0.0, max: 100.0, step: 1.0 }),
+            maxDistance: PD.Numeric(3, { min: 0, max: 256, step: 1 }),
             tolerance: PD.Numeric(1.0, { min: 0.0, max: 10.0, step: 0.1 }),
         }),
         off: PD.Group({})

+ 41 - 4
src/mol-geo/geometry/texture-mesh/texture-mesh.ts

@@ -7,7 +7,7 @@
 import { ValueCell } from '../../../mol-util';
 import { Sphere3D } from '../../../mol-math/geometry';
 import { ParamDefinition as PD } from '../../../mol-util/param-definition';
-import { LocationIterator } from '../../../mol-geo/util/location-iterator';
+import { LocationIterator, PositionLocation } from '../../../mol-geo/util/location-iterator';
 import { TransformData } from '../transform-data';
 import { createColors } from '../color-data';
 import { createMarkers } from '../marker-data';
@@ -20,11 +20,12 @@ import { createEmptyTransparency } from '../transparency-data';
 import { TextureMeshValues } from '../../../mol-gl/renderable/texture-mesh';
 import { calculateTransformBoundingSphere } from '../../../mol-gl/renderable/util';
 import { createNullTexture, Texture } from '../../../mol-gl/webgl/texture';
-import { Vec2, Vec4 } from '../../../mol-math/linear-algebra';
+import { Vec2, Vec3, Vec4 } from '../../../mol-math/linear-algebra';
 import { createEmptyClipping } from '../clipping-data';
 import { NullLocation } from '../../../mol-model/location';
 import { createEmptySubstance } from '../substance-data';
 import { RenderableState } from '../../../mol-gl/renderable';
+import { WebGLContext } from '../../../mol-gl/webgl/context';
 
 export interface TextureMesh {
     readonly kind: 'texture-mesh',
@@ -43,7 +44,10 @@ export interface TextureMesh {
 
     readonly boundingSphere: Sphere3D
 
-    readonly meta: { [k: string]: unknown }
+    readonly meta: {
+        webgl?: WebGLContext
+        [k: string]: unknown
+    }
 }
 
 export namespace TextureMesh {
@@ -131,9 +135,42 @@ export namespace TextureMesh {
         updateBoundingSphere,
         createRenderableState,
         updateRenderableState,
-        createPositionIterator: () => LocationIterator(1, 1, 1, () => NullLocation)
+        createPositionIterator,
     };
 
+    const TextureMeshName = 'texture-mesh';
+
+    function createPositionIterator(textureMesh: TextureMesh, transform: TransformData): LocationIterator {
+        const webgl = textureMesh.meta.webgl;
+        if (!webgl) return LocationIterator(1, 1, 1, () => NullLocation);
+
+        if (!webgl.namedFramebuffers[TextureMeshName]) {
+            webgl.namedFramebuffers[TextureMeshName] = webgl.resources.framebuffer();
+        }
+        const framebuffer = webgl.namedFramebuffers[TextureMeshName];
+        const [width, height] = textureMesh.geoTextureDim.ref.value;
+        const vertices = new Float32Array(width * height * 4);
+        framebuffer.bind();
+        textureMesh.vertexTexture.ref.value.attachFramebuffer(framebuffer, 0);
+        webgl.readPixels(0, 0, width, height, vertices);
+
+        const groupCount = textureMesh.vertexCount;
+        const instanceCount = transform.instanceCount.ref.value;
+        const location = PositionLocation();
+        const p = location.position;
+        const v = vertices;
+        const m = transform.aTransform.ref.value;
+        const getLocation = (groupIndex: number, instanceIndex: number) => {
+            if (instanceIndex < 0) {
+                Vec3.fromArray(p, v, groupIndex * 4);
+            } else {
+                Vec3.transformMat4Offset(p, v, m, 0, groupIndex * 4, instanceIndex * 16);
+            }
+            return location;
+        };
+        return LocationIterator(groupCount, instanceCount, 1, getLocation);
+    }
+
     function createValues(textureMesh: TextureMesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): TextureMeshValues {
         const { instanceCount, groupCount } = locationIt;
         const positionIt = Utils.createPositionIterator(textureMesh, transform);

+ 3 - 3
src/mol-gl/shader/direct-volume.frag.ts

@@ -270,16 +270,16 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) {
         #elif defined(dColorType_groupInstance)
             material.rgb = readFromTexture(tColor, vInstance * float(uGroupCount) + group, uColorTexDim).rgb;
         #elif defined(dColorType_vertex)
-            material.rgb = texture3dFrom1dTrilinear(tColor, isoPos, uGridDim, uColorTexDim, 0.0).rgb;
+            material.rgb = texture3dFrom1dTrilinear(tColor, unitPos, uGridDim, uColorTexDim, 0.0).rgb;
         #elif defined(dColorType_vertexInstance)
-            material.rgb = texture3dFrom1dTrilinear(tColor, isoPos, uGridDim, uColorTexDim, vInstance * float(uVertexCount)).rgb;
+            material.rgb = texture3dFrom1dTrilinear(tColor, unitPos, uGridDim, uColorTexDim, vInstance * float(uVertexCount)).rgb;
         #endif
 
         #ifdef dOverpaint
             #if defined(dOverpaintType_groupInstance)
                 overpaint = readFromTexture(tOverpaint, vInstance * float(uGroupCount) + group, uOverpaintTexDim);
             #elif defined(dOverpaintType_vertexInstance)
-                overpaint = texture3dFrom1dTrilinear(tOverpaint, isoPos, uGridDim, uOverpaintTexDim, vInstance * float(uVertexCount));
+                overpaint = texture3dFrom1dTrilinear(tOverpaint, unitPos, uGridDim, uOverpaintTexDim, vInstance * float(uVertexCount));
             #endif
 
             material.rgb = mix(material.rgb, overpaint.rgb, overpaint.a);

+ 1 - 1
src/mol-io/reader/cif/schema/bird.ts

@@ -1,7 +1,7 @@
 /**
  * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
- * Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.362, IHM 1.17, MA 1.4.3.
+ * Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.363, IHM 1.17, MA 1.4.3.
  *
  * @author molstar/ciftools package
  */

+ 1 - 1
src/mol-io/reader/cif/schema/ccd.ts

@@ -1,7 +1,7 @@
 /**
  * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
- * Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.362, IHM 1.17, MA 1.4.3.
+ * Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.363, IHM 1.17, MA 1.4.3.
  *
  * @author molstar/ciftools package
  */

+ 1 - 1
src/mol-io/reader/cif/schema/mmcif.ts

@@ -1,7 +1,7 @@
 /**
  * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
- * Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.362, IHM 1.17, MA 1.4.3.
+ * Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.363, IHM 1.17, MA 1.4.3.
  *
  * @author molstar/ciftools package
  */

File diff suppressed because it is too large
+ 0 - 0
src/mol-model/structure/model/types/saccharides.ts


+ 7 - 4
src/mol-plugin-ui/controls/parameters.tsx

@@ -18,7 +18,7 @@ import { getPrecision } from '../../mol-util/number';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { ParamMapping } from '../../mol-util/param-mapping';
 import { camelCaseToWords } from '../../mol-util/string';
-import { PluginUIComponent } from '../base';
+import { PluginReactContext, PluginUIComponent } from '../base';
 import { PluginUIContext } from '../context';
 import { ActionMenu } from './action-menu';
 import { ColorOptions, ColorValueOption, CombinedColorControl } from './color';
@@ -505,10 +505,12 @@ export class ValueRefControl extends React.PureComponent<ParamProps<PD.ValueRef<
 
     toggle = () => this.setState({ showOptions: !this.state.showOptions });
 
-    items = memoizeLatest((param: PD.ValueRef) => ActionMenu.createItemsFromSelectOptions(param.getOptions()));
+    private get items() {
+        return ActionMenu.createItemsFromSelectOptions(this.props.param.getOptions(this.context));
+    }
 
     renderControl() {
-        const items = this.items(this.props.param);
+        const items = this.items;
         const current = this.props.value.ref ? ActionMenu.findItem(items, this.props.value.ref) : void 0;
         const label = current
             ? current.label
@@ -521,7 +523,7 @@ export class ValueRefControl extends React.PureComponent<ParamProps<PD.ValueRef<
     renderAddOn() {
         if (!this.state.showOptions) return null;
 
-        const items = this.items(this.props.param);
+        const items = this.items;
         const current = ActionMenu.findItem(items, this.props.value.ref);
 
         return <ActionMenu items={items} current={current} onSelect={this.onSelect} />;
@@ -539,6 +541,7 @@ export class ValueRefControl extends React.PureComponent<ParamProps<PD.ValueRef<
         });
     }
 }
+ValueRefControl.contextType = PluginReactContext;
 
 export class IntervalControl extends React.PureComponent<ParamProps<PD.Interval>, { isExpanded: boolean }> {
     state = { isExpanded: false };

+ 4 - 4
src/mol-repr/representation.ts

@@ -140,7 +140,7 @@ export class RepresentationRegistry<D, S extends Representation.State> {
 //
 
 export { Representation };
-interface Representation<D, P extends PD.Params = {}, S extends Representation.State = Representation.State> {
+interface Representation<D, P extends PD.Params = PD.Params, S extends Representation.State = Representation.State> {
     readonly label: string
     readonly updated: Subject<number>
     /** Number of addressable groups in all visuals of the representation */
@@ -236,7 +236,7 @@ namespace Representation {
     }
     export const StateBuilder: StateBuilder<State> = { create: createState, update: updateState };
 
-    export type Any = Representation<any, any, any>
+    export type Any<P extends PD.Params = PD.Params, S extends State = State> = Representation<any, P, S>
     export const Empty: Any = {
         label: '', groupCount: 0, renderObjects: [], geometryVersion: -1, props: {}, params: {}, updated: new Subject(), state: createState(), theme: Theme.createEmpty(),
         createOrUpdate: () => Task.constant('', undefined),
@@ -248,7 +248,7 @@ namespace Representation {
         destroy: () => {}
     };
 
-    export type Def<D, P extends PD.Params = {}, S extends State = State> = { [k: string]: RepresentationFactory<D, P, S> }
+    export type Def<D, P extends PD.Params = PD.Params, S extends State = State> = { [k: string]: RepresentationFactory<D, P, S> }
 
     export class GeometryState {
         private curr = new Set<number>();
@@ -272,7 +272,7 @@ namespace Representation {
         }
     }
 
-    export function createMulti<D, P extends PD.Params = {}, S extends State = State>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<D, P>, stateBuilder: StateBuilder<S>, reprDefs: Def<D, P>): Representation<D, P, S> {
+    export function createMulti<D, P extends PD.Params = PD.Params, S extends State = State>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<D, P>, stateBuilder: StateBuilder<S>, reprDefs: Def<D, P>): Representation<D, P, S> {
         let version = 0;
         const updated = new Subject<number>();
         const geometryState = new GeometryState();

+ 2 - 0
src/mol-repr/structure/visual/gaussian-surface-mesh.ts

@@ -247,6 +247,7 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit,
     const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, densityTextureData.maxRadius);
     const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
     (surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution;
+    surface.meta.webgl = ctx.webgl;
 
     return surface;
 }
@@ -321,6 +322,7 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str
     const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, densityTextureData.maxRadius);
     const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
     (surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution;
+    surface.meta.webgl = ctx.webgl;
 
     return surface;
 }

+ 1 - 0
src/mol-repr/volume/isosurface.ts

@@ -201,6 +201,7 @@ async function createVolumeIsosurfaceTextureMesh(ctx: VisualContext, volume: Vol
 
     const groupCount = volume.grid.cells.data.length;
     const surface = TextureMesh.create(gv.vertexCount, groupCount, gv.vertexTexture, gv.groupTexture, gv.normalTexture, Volume.getBoundingSphere(volume), textureMesh);
+    surface.meta.webgl = ctx.webgl;
 
     return surface;
 }

+ 2 - 0
src/mol-theme/color.ts

@@ -40,6 +40,7 @@ import { VolumeValueColorThemeProvider } from './color/volume-value';
 import { Vec3, Vec4 } from '../mol-math/linear-algebra';
 import { ModelIndexColorThemeProvider } from './color/model-index';
 import { StructureIndexColorThemeProvider } from './color/structure-index';
+import { ExternalVolumeColorThemeProvider } from './color/external-volume';
 
 export type LocationColor = (location: Location, isSecondary: boolean) => Color
 
@@ -152,6 +153,7 @@ namespace ColorTheme {
         'unit-index': UnitIndexColorThemeProvider,
         'uniform': UniformColorThemeProvider,
         'volume-value': VolumeValueColorThemeProvider,
+        'external-volume': ExternalVolumeColorThemeProvider,
     };
     type _BuiltIn = typeof BuiltIn
     export type BuiltIn = keyof _BuiltIn

+ 159 - 0
src/mol-theme/color/external-volume.ts

@@ -0,0 +1,159 @@
+/**
+ * Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { Color, ColorScale } from '../../mol-util/color';
+import { Location } from '../../mol-model/location';
+import { ColorTheme } from '../color';
+import { ParamDefinition as PD } from '../../mol-util/param-definition';
+import { ThemeDataContext } from '../theme';
+import { Grid, Volume } from '../../mol-model/volume';
+import { type PluginContext } from '../../mol-plugin/context';
+import { isPositionLocation } from '../../mol-geo/util/location-iterator';
+import { Mat4, Vec3 } from '../../mol-math/linear-algebra';
+import { lerp } from '../../mol-math/interpolate';
+
+const Description = `Assigns a color based volume value at a given vertex.`;
+
+export const ExternalVolumeColorThemeParams = {
+    volume: PD.ValueRef<Volume>(
+        (ctx: PluginContext) => {
+            const volumes = ctx.state.data.selectQ(q => q.root.subtree().filter(c => Volume.is(c.obj?.data)));
+            return volumes.map(v => [v.transform.ref, v.obj?.label ?? '<unknown>'] as [string, string]);
+        },
+        (ref, getData) => getData(ref),
+    ),
+    coloring: PD.MappedStatic('absolute-value', {
+        'absolute-value': PD.Group({
+            domain: PD.MappedStatic('auto', {
+                custom: PD.Interval([-1, 1]),
+                auto: PD.Group({
+                    symmetric: PD.Boolean(false, { description: 'If true the automatic range is determined as [-|max|, |max|].' })
+                })
+            }),
+            list: PD.ColorList('red-white-blue', { presetKind: 'scale' })
+        }),
+        'relative-value': PD.Group({
+            domain: PD.MappedStatic('auto', {
+                custom: PD.Interval([-1, 1]),
+                auto: PD.Group({
+                    symmetric: PD.Boolean(false, { description: 'If true the automatic range is determined as [-|max|, |max|].' })
+                })
+            }),
+            list: PD.ColorList('red-white-blue', { presetKind: 'scale' })
+        })
+    }),
+    defaultColor: PD.Color(Color(0xcccccc)),
+};
+export type ExternalVolumeColorThemeParams = typeof ExternalVolumeColorThemeParams
+
+export function ExternalVolumeColorTheme(ctx: ThemeDataContext, props: PD.Values<ExternalVolumeColorThemeParams>): ColorTheme<ExternalVolumeColorThemeParams> {
+    let volume: Volume | undefined;
+    try {
+        volume = props.volume.getValue();
+    } catch {
+        // .getValue() is resolved during state reconciliation => would throw from UI
+    }
+
+    // NOTE: this will currently be slow for with GPU/texture meshes due to slow iteration
+    // TODO: create texture to be able to do the sampling on the GPU
+
+    let color;
+    if (volume) {
+        const coloring = props.coloring.params;
+        const { stats } = volume.grid;
+        const domain: [number, number] = coloring.domain.name === 'custom' ? coloring.domain.params : [stats.min, stats.max];
+
+        const isRelative = props.coloring.name === 'relative-value';
+        if (coloring.domain.name === 'auto' && isRelative) {
+            domain[0] = (domain[0] - stats.mean) / stats.sigma;
+            domain[1] = (domain[1] - stats.mean) / stats.sigma;
+        }
+
+        if (props.coloring.params.domain.name === 'auto' && props.coloring.params.domain.params.symmetric) {
+            const max = Math.max(Math.abs(domain[0]), Math.abs(domain[1]));
+            domain[0] = -max;
+            domain[1] = max;
+        }
+
+        const scale = ColorScale.create({ domain, listOrName: coloring.list.colors });
+
+        const cartnToGrid = Grid.getGridToCartesianTransform(volume.grid);
+        Mat4.invert(cartnToGrid, cartnToGrid);
+        const gridCoords = Vec3();
+
+        const { dimensions, get } = volume.grid.cells.space;
+        const data = volume.grid.cells.data;
+
+        const [mi, mj, mk] = dimensions;
+
+        color = (location: Location): Color => {
+            if (!isPositionLocation(location)) {
+                return props.defaultColor;
+            }
+
+            Vec3.copy(gridCoords, location.position);
+            Vec3.transformMat4(gridCoords, gridCoords, cartnToGrid);
+
+            const i = Math.floor(gridCoords[0]);
+            const j = Math.floor(gridCoords[1]);
+            const k = Math.floor(gridCoords[2]);
+
+            if (i < 0 || i >= mi || j < 0 || j >= mj || k < 0 || k >= mk) {
+                return props.defaultColor;
+            }
+
+            const u = gridCoords[0] - i;
+            const v = gridCoords[1] - j;
+            const w = gridCoords[2] - k;
+
+            // Tri-linear interpolation for the value
+            const ii = Math.min(i + 1, mi - 1);
+            const jj = Math.min(j + 1, mj - 1);
+            const kk = Math.min(k + 1, mk - 1);
+
+            let a = get(data, i, j, k);
+            let b = get(data, ii, j, k);
+            let c = get(data, i, jj, k);
+            let d = get(data, ii, jj, k);
+            const x = lerp(lerp(a, b, u), lerp(c, d, u), v);
+
+            a = get(data, i, j, kk);
+            b = get(data, ii, j, kk);
+            c = get(data, i, jj, kk);
+            d = get(data, ii, jj, kk);
+            const y = lerp(lerp(a, b, u), lerp(c, d, u), v);
+
+            let value = lerp(x, y, w);
+            if (isRelative) {
+                value = (value - stats.mean) / stats.sigma;
+            }
+
+            return scale.color(value);
+        };
+    } else {
+        color = () => props.defaultColor;
+    }
+
+    return {
+        factory: ExternalVolumeColorTheme,
+        granularity: 'vertex',
+        preferSmoothing: true,
+        color,
+        props,
+        description: Description,
+        // TODO: figure out how to do legend for this
+    };
+}
+
+export const ExternalVolumeColorThemeProvider: ColorTheme.Provider<ExternalVolumeColorThemeParams, 'external-volume'> = {
+    name: 'external-volume',
+    label: 'External Volume',
+    category: ColorTheme.Category.Misc,
+    factory: ExternalVolumeColorTheme,
+    getParams: () => ExternalVolumeColorThemeParams,
+    defaultValues: PD.getDefaultValues(ExternalVolumeColorThemeParams),
+    isApplicable: (ctx: ThemeDataContext) => true,
+};

+ 6 - 6
src/mol-util/param-definition.ts

@@ -290,9 +290,9 @@ export namespace ParamDefinition {
     // getValue needs to be assigned by a runtime because it might not be serializable
     export interface ValueRef<T = any> extends Base<{ ref: string, getValue: () => T }> {
         type: 'value-ref',
-        resolveRef: (ref: string) => T,
+        resolveRef: (ref: string, getData: (ref: string) => any) => T,
         // a provider because the list changes over time
-        getOptions: () => Select<string>['options'],
+        getOptions: (ctx: any) => Select<string>['options'],
     }
     export function ValueRef<T>(getOptions: ValueRef['getOptions'], resolveRef: ValueRef<T>['resolveRef'], info?: Info & { defaultRef?: string }) {
         return setInfo<ValueRef<T>>({ type: 'value-ref', defaultValue: { ref: info?.defaultRef ?? '', getValue: unsetGetValue as any }, getOptions, resolveRef }, info);
@@ -365,8 +365,8 @@ export namespace ParamDefinition {
         return d as Values<T>;
     }
 
-    function _resolveRef(resolve: (ref: string) => any, ref: string) {
-        return () => resolve(ref);
+    function _resolveRef(resolve: (ref: string, getData: (ref: string) => any) => any, ref: string, getData: (ref: string) => any) {
+        return () => resolve(ref, getData);
     }
 
     function resolveRefValue(p: Any, value: any, getData: (ref: string) => any) {
@@ -375,11 +375,11 @@ export namespace ParamDefinition {
         if (p.type === 'value-ref') {
             const v = value as ValueRef['defaultValue'];
             if (!v.ref) v.getValue = () => { throw new Error('Unset ref in ValueRef value.'); };
-            else v.getValue = _resolveRef(p.resolveRef, v.ref);
+            else v.getValue = _resolveRef(p.resolveRef, v.ref, getData);
         } else if (p.type === 'data-ref') {
             const v = value as ValueRef['defaultValue'];
             if (!v.ref) v.getValue = () => { throw new Error('Unset ref in ValueRef value.'); };
-            else v.getValue = _resolveRef(getData, v.ref);
+            else v.getValue = _resolveRef(getData, v.ref, getData);
         } else if (p.type === 'group') {
             resolveRefs(p.params, value, getData);
         } else if (p.type === 'mapped') {

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